OMCompiler/Compiler/FrontEnd/InstBinding.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 InstBinding | ||
| 37 | " file: InstBinding.mo | ||
| 38 | package: InstBinding | ||
| 39 | description: Binding instantiation | ||
| 40 | |||
| 41 | |||
| 42 | This module is responsible for instantiation of bindings. | ||
| 43 | " | ||
| 44 | |||
| 45 | public import Absyn; | ||
| 46 | public import AbsynUtil; | ||
| 47 | public import ClassInf; | ||
| 48 | public import DAE; | ||
| 49 | public import FCore; | ||
| 50 | public import FGraph; | ||
| 51 | public import InnerOuter; | ||
| 52 | public import Mod; | ||
| 53 | public import SCode; | ||
| 54 | public import Values; | ||
| 55 | |||
| 56 | protected type Ident = DAE.Ident "an identifier"; | ||
| 57 | protected type InstanceHierarchy = InnerOuter.InstHierarchy "an instance hierarchy"; | ||
| 58 | protected type InstDims = list<list<DAE.Dimension>>; | ||
| 59 | |||
| 60 | protected import Ceval; | ||
| 61 | protected import ComponentReference; | ||
| 62 | protected import ComponentReferenceBasics; | ||
| 63 | protected import ElementSource; | ||
| 64 | protected import Error; | ||
| 65 | protected import Expression; | ||
| 66 | protected import ExpressionSimplify; | ||
| 67 | protected import InstUtil; | ||
| 68 | protected import List; | ||
| 69 | protected import Flags; | ||
| 70 | protected import Debug; | ||
| 71 | protected import DAEUtil; | ||
| 72 | protected import PrefixUtil; | ||
| 73 | import SCodeUtil; | ||
| 74 | protected import Types; | ||
| 75 | protected import InstSection; | ||
| 76 | protected import ValuesUtil; | ||
| 77 | protected import ExpressionBasics; | ||
| 78 | |||
| 79 | public constant DAE.Type stateSelectType = | ||
| 80 | DAE.T_ENUMERATION(NONE(),Absyn.IDENT(""),{"never","avoid","default","prefer","always"}, | ||
| 81 | { | ||
| 82 | DAE.TYPES_VAR("never",DAE.dummyAttrParam, | ||
| 83 | DAE.T_ENUMERATION(SOME(1),Absyn.IDENT(""),{"never","avoid","default","prefer","always"},{},{}),DAE.UNBOUND(),false,NONE()), | ||
| 84 | DAE.TYPES_VAR("avoid",DAE.dummyAttrParam, | ||
| 85 | DAE.T_ENUMERATION(SOME(2),Absyn.IDENT(""),{"never","avoid","default","prefer","always"},{},{}),DAE.UNBOUND(),false,NONE()), | ||
| 86 | DAE.TYPES_VAR("default",DAE.dummyAttrParam, | ||
| 87 | DAE.T_ENUMERATION(SOME(3),Absyn.IDENT(""),{"never","avoid","default","prefer","always"},{},{}),DAE.UNBOUND(),false,NONE()), | ||
| 88 | DAE.TYPES_VAR("prefer",DAE.dummyAttrParam, | ||
| 89 | DAE.T_ENUMERATION(SOME(4),Absyn.IDENT(""),{"never","avoid","default","prefer","always"},{},{}),DAE.UNBOUND(),false,NONE()), | ||
| 90 | DAE.TYPES_VAR("always",DAE.dummyAttrParam, | ||
| 91 | DAE.T_ENUMERATION(SOME(5),Absyn.IDENT(""),{"never","avoid","default","prefer","always"},{},{}),DAE.UNBOUND(),false,NONE()) | ||
| 92 | },{}); | ||
| 93 | |||
| 94 | public constant DAE.Type uncertaintyType = | ||
| 95 | DAE.T_ENUMERATION(NONE(),Absyn.IDENT(""),{"given","sought","refine","propagate"}, | ||
| 96 | { | ||
| 97 | DAE.TYPES_VAR("given",DAE.dummyAttrParam, | ||
| 98 | DAE.T_ENUMERATION(SOME(1),Absyn.IDENT(""),{"given","sought","refine","propagate"},{},{}),DAE.UNBOUND(),false,NONE()), | ||
| 99 | DAE.TYPES_VAR("sought",DAE.dummyAttrParam, | ||
| 100 | DAE.T_ENUMERATION(SOME(2),Absyn.IDENT(""),{"given","sought","refine","propagate"},{},{}),DAE.UNBOUND(),false,NONE()), | ||
| 101 | DAE.TYPES_VAR("refine",DAE.dummyAttrParam, | ||
| 102 | DAE.T_ENUMERATION(SOME(3),Absyn.IDENT(""),{"given","sought","refine","propagate"},{},{}),DAE.UNBOUND(),false,NONE()), | ||
| 103 | DAE.TYPES_VAR("propagate",DAE.dummyAttrParam, | ||
| 104 | DAE.T_ENUMERATION(SOME(4),Absyn.IDENT(""),{"given","sought","refine","propagate"},{},{}),DAE.UNBOUND(),false,NONE()) | ||
| 105 | },{}); | ||
| 106 | |||
| 107 | public constant DAE.Type distributionType = | ||
| 108 | DAE.T_COMPLEX(ClassInf.RECORD(Absyn.IDENT("Distribution")), | ||
| 109 | { | ||
| 110 | DAE.TYPES_VAR( | ||
| 111 | "name", | ||
| 112 | DAE.ATTR(DAE.NON_CONNECTOR(),SCode.NON_PARALLEL(),SCode.PARAM(),Absyn.BIDIR(),Absyn.NOT_INNER_OUTER(),SCode.PUBLIC()), | ||
| 113 | DAE.T_STRING_DEFAULT, | ||
| 114 | DAE.UNBOUND(), // binding | ||
| 115 | false, | ||
| 116 | NONE()), | ||
| 117 | DAE.TYPES_VAR( | ||
| 118 | "params", | ||
| 119 | DAE.ATTR(DAE.NON_CONNECTOR(),SCode.NON_PARALLEL(),SCode.PARAM(),Absyn.BIDIR(),Absyn.NOT_INNER_OUTER(),SCode.PUBLIC()), | ||
| 120 | DAE.T_ARRAY_REAL_NODIM, | ||
| 121 | DAE.UNBOUND(), // binding | ||
| 122 | false, | ||
| 123 | NONE()), | ||
| 124 | DAE.TYPES_VAR( | ||
| 125 | "paramNames", | ||
| 126 | DAE.ATTR(DAE.NON_CONNECTOR(),SCode.NON_PARALLEL(),SCode.PARAM(),Absyn.BIDIR(),Absyn.NOT_INNER_OUTER(),SCode.PUBLIC()), | ||
| 127 | DAE.T_ARRAY_STRING_NODIM, | ||
| 128 | DAE.UNBOUND(), // binding | ||
| 129 | false, | ||
| 130 | NONE()) | ||
| 131 | }, | ||
| 132 | NONE(), | ||
| 133 | false); | ||
| 134 | |||
| 135 | protected function instBinding | ||
| 136 | "This function investigates a modification and extracts the | ||
| 137 | <...> modification. E.g. Real x(<...>=1+3) => 1+3 | ||
| 138 | It also handles the case Integer T0[2](final <...>={5,6})={9,10} becomes | ||
| 139 | Integer T0[1](<...>=5); Integer T0[2](<...>=6); | ||
| 140 | |||
| 141 | If no modifier is given it also investigates the type to check for binding there. | ||
| 142 | I.e. type A = Real(start=1); A a; will set the start attribute since it's found in the type. | ||
| 143 | |||
| 144 | Arg 1 is the modification | ||
| 145 | Arg 2 are the type variables. | ||
| 146 | Arg 3 is the expected type that the modification should have | ||
| 147 | Arg 4 is the index list for the element: for T0{1,2} is {1,2}" | ||
| 148 | input DAE.Mod inMod; | ||
| 149 | input list<DAE.Var> inVarLst; | ||
| 150 | input DAE.Type inType; | ||
| 151 | input list<Integer> inIntegerLst; | ||
| 152 | input String inString; | ||
| 153 | input Boolean useConstValue "if true use constant value present in TYPED (if present)"; | ||
| 154 | output Option<DAE.Exp> outExpExpOption; | ||
| 155 | algorithm | ||
| 156 | outExpExpOption := matchcontinue (inMod,inVarLst,inType,inIntegerLst,inString) | ||
| 157 | local | ||
| 158 | DAE.Mod mod2,mod; | ||
| 159 | DAE.Exp e,e_1; | ||
| 160 | DAE.Type ty2,expected_type,etype; | ||
| 161 | String bind_name; | ||
| 162 | Option<DAE.Exp> result; | ||
| 163 | list<Integer> index_list; | ||
| 164 | DAE.Binding binding; | ||
| 165 | Ident name; | ||
| 166 | Option<Values.Value> optVal; | ||
| 167 | list<DAE.Var> varLst; | ||
| 168 | |||
| 169 | case (mod,_,expected_type,{},bind_name) /* No subscript/index */ | ||
| 170 | algorithm | ||
| 171 | 12418013 | mod2 := Mod.lookupCompModification(mod, bind_name); | |
| 172 |
5/8✗ Branch 1 not taken.
✓ Branch 2 taken 12418013 times.
✓ Branch 3 taken 12326749 times.
✓ Branch 4 taken 91264 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 91264 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 91264 times.
|
12418013 | SOME(DAE.TYPED(e,optVal,DAE.PROP(ty2,_),_)) := Mod.modEquation(mod2); |
| 173 | 91264 | (e_1,_) := Types.matchType(e, ty2, expected_type, true); | |
| 174 | 91120 | e_1 := InstUtil.checkUseConstValue(useConstValue,e_1,optVal); | |
| 175 | then | ||
| 176 | SOME(e_1); | ||
| 177 | |||
| 178 | case (mod,_,etype,index_list,bind_name) /* Have subscript/index */ | ||
| 179 | algorithm | ||
| 180 | 12326893 | mod2 := Mod.lookupCompModification(mod, bind_name); | |
| 181 | 12326893 | result := instBinding2(mod2, etype, index_list, bind_name, useConstValue); | |
| 182 | then | ||
| 183 | result; | ||
| 184 | |||
| 185 | case (mod,_,_,{},bind_name) /* No modifier for this name. */ | ||
| 186 | algorithm | ||
| 187 |
1/2✓ Branch 0 taken 12326893 times.
✗ Branch 1 not taken.
|
12326893 | failure(Mod.lookupCompModification(mod, bind_name)); |
| 188 | then | ||
| 189 | NONE(); | ||
| 190 | |||
| 191 | case (_,DAE.TYPES_VAR(name=name,binding=binding)::_,_,_,bind_name) | ||
| 192 | algorithm | ||
| 193 |
4/4✓ Branch 0 taken 554020 times.
✓ Branch 1 taken 5067053 times.
✓ Branch 3 taken 123151 times.
✓ Branch 4 taken 430869 times.
|
5621073 | true := stringEq(name, bind_name); |
| 194 | 430869 | then | |
| 195 | DAEUtil.bindingExp(binding); | ||
| 196 | |||
| 197 | case (mod,_::varLst,etype,index_list,bind_name) | ||
| 198 | 5190204 | then instBinding(mod,varLst,etype,index_list,bind_name,useConstValue); | |
| 199 | |||
| 200 | case (_,{},_,_,_) | ||
| 201 | then NONE(); | ||
| 202 | end matchcontinue; | ||
| 203 | end instBinding; | ||
| 204 | |||
| 205 | protected function instBinding2 | ||
| 206 | "This function investigates a modification and extracts the <...> | ||
| 207 | modification if the modification is in array of components. | ||
| 208 | Help-function to instBinding" | ||
| 209 | input DAE.Mod inMod; | ||
| 210 | input DAE.Type inType; | ||
| 211 | input list<Integer> inIntegerLst; | ||
| 212 | input String inString; | ||
| 213 | input Boolean useConstValue "if true, use constant value in TYPED (if present)"; | ||
| 214 | output Option<DAE.Exp> outExpExpOption; | ||
| 215 | algorithm | ||
| 216 | outExpExpOption:= | ||
| 217 | match (inMod,inType,inIntegerLst,inString) | ||
| 218 | local | ||
| 219 | DAE.Mod mod2,mod; | ||
| 220 | DAE.Exp e,e_1; | ||
| 221 | DAE.Type ty2,etype; | ||
| 222 | Integer index; | ||
| 223 | String bind_name; | ||
| 224 | Option<DAE.Exp> result; | ||
| 225 | list<Integer> res; | ||
| 226 | Option<Values.Value> optVal; | ||
| 227 | case (mod,etype,(index :: {}),_) /* Only one element in the index-list */ | ||
| 228 | algorithm | ||
| 229 | ✗ | mod2 := Mod.lookupIdxModification(mod, DAE.ICONST(index)); | |
| 230 | ✗ | SOME(DAE.TYPED(e,optVal,DAE.PROP(ty2,_),_)) := Mod.modEquation(mod2); | |
| 231 | ✗ | (e_1,_) := Types.matchType(e, ty2, etype, true); | |
| 232 | ✗ | e_1 := InstUtil.checkUseConstValue(useConstValue,e_1,optVal); | |
| 233 | then | ||
| 234 | SOME(e_1); | ||
| 235 | case (mod,etype,(index :: res),bind_name) /* Several elements in the index-list */ | ||
| 236 | algorithm | ||
| 237 | result := matchcontinue() | ||
| 238 | case () | ||
| 239 | algorithm | ||
| 240 | ✗ | mod2 := Mod.lookupIdxModification(mod, DAE.ICONST(index)); | |
| 241 | ✗ | result := instBinding2(mod2, etype, res, bind_name,useConstValue); | |
| 242 | then result; | ||
| 243 | else NONE(); | ||
| 244 | end matchcontinue; | ||
| 245 | then | ||
| 246 | result; | ||
| 247 | end match; | ||
| 248 | end instBinding2; | ||
| 249 | |||
| 250 | public function instStartBindingExp | ||
| 251 | "This function investigates a modification and extracts the | ||
| 252 | start modification. E.g. Real x(start=1+3) => 1+3 | ||
| 253 | It also handles the case Integer T0{2}(final start={5,6})={9,10} becomes | ||
| 254 | Integer T0{1}(start=5); Integer T0{2}(start=6); | ||
| 255 | |||
| 256 | Arg 1 is the start modification | ||
| 257 | Arg 2 is the expected type that the modification should have | ||
| 258 | Arg 3 is variability of the element" | ||
| 259 | input DAE.Mod inMod; | ||
| 260 | input DAE.Type inExpectedType; | ||
| 261 | input SCode.Variability inVariability; | ||
| 262 | output DAE.StartValue outStartValue; | ||
| 263 | algorithm | ||
| 264 |
2/2✓ Branch 1 taken 423500 times.
✓ Branch 2 taken 103066 times.
|
526566 | if SCodeUtil.isConstant(inVariability) then |
| 265 | outStartValue := NONE(); | ||
| 266 | else | ||
| 267 | // When instantiating arrays, the array type is passed. | ||
| 268 | // But binding is performed on the element type. | ||
| 269 | 423500 | outStartValue := instBinding(inMod, {}, | |
| 270 | Types.arrayElementType(inExpectedType), {}, "start", false); | ||
| 271 | end if; | ||
| 272 | end instStartBindingExp; | ||
| 273 | |||
| 274 | protected function instStartOrigin | ||
| 275 | "This function investigates if the start value comes from the modification or the type" | ||
| 276 | input DAE.Mod inMod; | ||
| 277 | input list<DAE.Var> inVarLst; | ||
| 278 | input String inString; | ||
| 279 | output Option<DAE.StartOrigin> outStartOrigin; | ||
| 280 | algorithm | ||
| 281 | outStartOrigin := matchcontinue (inMod,inVarLst,inString) | ||
| 282 | local | ||
| 283 | DAE.Mod mod2,mod; | ||
| 284 | String bind_name; | ||
| 285 | Ident name; | ||
| 286 | list<DAE.Var> varLst; | ||
| 287 | |||
| 288 | case (mod,_,bind_name) | ||
| 289 | algorithm | ||
| 290 | 1022389 | mod2 := Mod.lookupCompModification(mod, bind_name); | |
| 291 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 1022389 times.
✓ Branch 3 taken 1002682 times.
✓ Branch 4 taken 19707 times.
|
1022389 | SOME(_) := Mod.modEquation(mod2); |
| 292 | then | ||
| 293 | SOME(DAE.StartOrigin.BINDING_ORIGIN()); | ||
| 294 | |||
| 295 | case (_,DAE.TYPES_VAR(name=name)::_,bind_name) | ||
| 296 | algorithm | ||
| 297 |
4/4✓ Branch 0 taken 19072 times.
✓ Branch 1 taken 357346 times.
✓ Branch 3 taken 18818 times.
✓ Branch 4 taken 254 times.
|
376418 | true := stringEq(name, bind_name); |
| 298 | then | ||
| 299 | SOME(DAE.StartOrigin.TYPE_ORIGIN()); | ||
| 300 | |||
| 301 | case (mod,_::varLst,bind_name) | ||
| 302 | 357600 | then instStartOrigin(mod,varLst,bind_name); | |
| 303 | |||
| 304 | case (_,{},_) | ||
| 305 | then NONE(); | ||
| 306 | end matchcontinue; | ||
| 307 | end instStartOrigin; | ||
| 308 | |||
| 309 | public function instDaeVariableAttributes | ||
| 310 | "this function extracts the attributes from the modification | ||
| 311 | It returns a DAE.VariableAttributes option because | ||
| 312 | somtimes a varible does not contain the variable-attr." | ||
| 313 | input FCore.Cache inCache; | ||
| 314 | input FCore.Graph inEnv; | ||
| 315 | input DAE.Mod inMod; | ||
| 316 | input DAE.Type inType; | ||
| 317 | input list<Integer> inIntegerLst; | ||
| 318 | output FCore.Cache outCache; | ||
| 319 | output Option<DAE.VariableAttributes> outDAEVariableAttributesOption; | ||
| 320 | algorithm | ||
| 321 | (outCache,outDAEVariableAttributesOption) := | ||
| 322 | matchcontinue (inCache, inMod, inType, inIntegerLst) | ||
| 323 | local | ||
| 324 | Option<DAE.Exp> quantity_str,unit_str,displayunit_str,nominal_val,fixed_val,exp_bind_select,exp_bind_uncertainty,exp_bind_min,exp_bind_max,exp_bind_start,min_val,max_val,start_val; | ||
| 325 | Option<DAE.StartOrigin> startOrigin; | ||
| 326 | Option<DAE.StateSelect> stateSelect_value; | ||
| 327 | Option<DAE.Uncertainty> uncertainty_value; | ||
| 328 | Option<DAE.Distribution> distribution_value; | ||
| 329 | DAE.Mod mod; | ||
| 330 | list<Integer> index_list; | ||
| 331 | DAE.Type enumtype; | ||
| 332 | FCore.Cache cache; | ||
| 333 | DAE.Type tp; | ||
| 334 | list<DAE.Var> varLst; | ||
| 335 | |||
| 336 | // Real | ||
| 337 | case (cache, mod, DAE.T_REAL(varLst = varLst), index_list) | ||
| 338 | algorithm | ||
| 339 | 448678 | quantity_str := instBinding(mod, varLst, DAE.T_STRING_DEFAULT,index_list, "quantity",false); | |
| 340 | 448678 | unit_str := instBinding(mod, varLst, DAE.T_STRING_DEFAULT, index_list, "unit",false); | |
| 341 | 448678 | displayunit_str := instBinding(mod, varLst,DAE.T_STRING_DEFAULT, index_list, "displayUnit",false); | |
| 342 | 448678 | min_val := instBinding(mod, varLst, DAE.T_REAL_DEFAULT,index_list, "min",false); | |
| 343 | 448678 | max_val := instBinding(mod, varLst, DAE.T_REAL_DEFAULT,index_list, "max",false); | |
| 344 | 448678 | start_val := instBinding(mod, varLst, DAE.T_REAL_DEFAULT,index_list, "start",false); | |
| 345 | 448678 | fixed_val := instBinding( mod, varLst, DAE.T_BOOL_DEFAULT,index_list, "fixed",true); | |
| 346 | 448678 | nominal_val := instBinding(mod, varLst, DAE.T_REAL_DEFAULT,index_list, "nominal",false); | |
| 347 | |||
| 348 | 448678 | exp_bind_select := instEnumerationBinding(mod, varLst, index_list, "stateSelect",stateSelectType,true); | |
| 349 | 448678 | stateSelect_value := InstUtil.getStateSelectFromExpOption(exp_bind_select); | |
| 350 | |||
| 351 | 448678 | exp_bind_uncertainty := instEnumerationBinding(mod, varLst, index_list, "uncertain",uncertaintyType,true); | |
| 352 | 448678 | uncertainty_value := getUncertainFromExpOption(exp_bind_uncertainty); | |
| 353 | 448678 | distribution_value := instDistributionBinding(mod, varLst, index_list, "distribution", false); | |
| 354 | 448678 | startOrigin := instStartOrigin(mod, varLst, "start"); | |
| 355 | |||
| 356 | //TODO: check for protected attribute (here and below matches) | ||
| 357 | 448678 | then | |
| 358 | (cache,SOME( | ||
| 359 | DAE.VAR_ATTR_REAL(quantity_str,unit_str,displayunit_str,min_val,max_val, | ||
| 360 | start_val,fixed_val,nominal_val,stateSelect_value,uncertainty_value,distribution_value,NONE(),NONE(),NONE(),startOrigin))); | ||
| 361 | |||
| 362 | // Integer | ||
| 363 | case (cache, mod, DAE.T_INTEGER(varLst = varLst), index_list) | ||
| 364 | algorithm | ||
| 365 | 44782 | quantity_str := instBinding(mod, varLst, DAE.T_STRING_DEFAULT, index_list, "quantity",false); | |
| 366 | 44782 | min_val := instBinding(mod, varLst, DAE.T_INTEGER_DEFAULT, index_list, "min",false); | |
| 367 | 44782 | max_val := instBinding(mod, varLst, DAE.T_INTEGER_DEFAULT, index_list, "max",false); | |
| 368 | 44782 | start_val := instBinding(mod, varLst, DAE.T_INTEGER_DEFAULT, index_list, "start",false); | |
| 369 | 44782 | fixed_val := instBinding(mod, varLst, DAE.T_BOOL_DEFAULT,index_list, "fixed",true); | |
| 370 | 44782 | exp_bind_uncertainty := instEnumerationBinding(mod, varLst, index_list, "uncertain",uncertaintyType,true); | |
| 371 | 44782 | uncertainty_value := getUncertainFromExpOption(exp_bind_uncertainty); | |
| 372 | 44782 | distribution_value := instDistributionBinding(mod, varLst, index_list, "distribution", false); | |
| 373 | |||
| 374 | 44782 | startOrigin := instStartOrigin(mod, varLst, "start"); | |
| 375 | 44782 | then | |
| 376 | (cache,SOME(DAE.VAR_ATTR_INT(quantity_str,min_val,max_val,start_val,fixed_val,uncertainty_value,distribution_value,NONE(),NONE(),NONE(),startOrigin))); | ||
| 377 | |||
| 378 | // Boolean | ||
| 379 | case (cache, mod, tp as DAE.T_BOOL(varLst = varLst), index_list) | ||
| 380 | algorithm | ||
| 381 | 67079 | quantity_str := instBinding( mod, varLst, DAE.T_STRING_DEFAULT, index_list, "quantity",false); | |
| 382 | 67079 | start_val := instBinding(mod, varLst, tp, index_list, "start",false); | |
| 383 | 67079 | fixed_val := instBinding(mod, varLst, tp, index_list, "fixed",true); | |
| 384 | 67079 | startOrigin := instStartOrigin(mod, varLst, "start"); | |
| 385 | 67079 | then | |
| 386 | (cache,SOME(DAE.VAR_ATTR_BOOL(quantity_str,start_val,fixed_val,NONE(),NONE(),NONE(),startOrigin))); | ||
| 387 | |||
| 388 | // BTH Clock | ||
| 389 | case (cache, _, DAE.T_CLOCK(), _) | ||
| 390 | then | ||
| 391 | (cache,SOME(DAE.VAR_ATTR_CLOCK(NONE(),NONE()))); | ||
| 392 | |||
| 393 | // String | ||
| 394 | case (cache, mod, tp as DAE.T_STRING(varLst = varLst), index_list) | ||
| 395 | algorithm | ||
| 396 | 77015 | quantity_str := instBinding(mod, varLst, tp, index_list, "quantity",false); | |
| 397 | 77015 | start_val := instBinding(mod, varLst, tp, index_list, "start",false); | |
| 398 | 77015 | fixed_val := instBinding(mod, varLst, DAE.T_BOOL_DEFAULT, index_list, "fixed",true); | |
| 399 | 77015 | startOrigin := instStartOrigin(mod, varLst, "start"); | |
| 400 | 77015 | then | |
| 401 | (cache,SOME(DAE.VAR_ATTR_STRING(quantity_str,start_val,fixed_val,NONE(),NONE(),NONE(),startOrigin))); | ||
| 402 | |||
| 403 | // Enumeration | ||
| 404 | case (cache, mod, enumtype as DAE.T_ENUMERATION(attributeLst = varLst), index_list) | ||
| 405 | algorithm | ||
| 406 | 27235 | quantity_str := instBinding(mod, varLst, DAE.T_STRING_DEFAULT,index_list, "quantity",false); | |
| 407 | 27235 | exp_bind_min := instBinding(mod, varLst, enumtype, index_list, "min",false); | |
| 408 | 27235 | exp_bind_max := instBinding(mod, varLst, enumtype, index_list, "max",false); | |
| 409 | 27235 | exp_bind_start := instBinding(mod, varLst, enumtype, index_list, "start",false); | |
| 410 | 27235 | fixed_val := instBinding(mod, varLst, DAE.T_BOOL_DEFAULT, index_list, "fixed",true); | |
| 411 | 27235 | startOrigin := instStartOrigin(mod, varLst, "start"); | |
| 412 | 27235 | then | |
| 413 | (cache,SOME(DAE.VAR_ATTR_ENUMERATION(quantity_str,exp_bind_min,exp_bind_max,exp_bind_start,fixed_val,NONE(),NONE(),NONE(),startOrigin))); | ||
| 414 | |||
| 415 | // not a basic type? | ||
| 416 | case (cache, _, _, _) | ||
| 417 | then (cache,NONE()); | ||
| 418 | end matchcontinue; | ||
| 419 | end instDaeVariableAttributes; | ||
| 420 | |||
| 421 | protected function instEnumerationBinding | ||
| 422 | "author: LP | ||
| 423 | instantiates a enumeration binding and retrieves the value." | ||
| 424 | input DAE.Mod inMod; | ||
| 425 | input list<DAE.Var> varLst; | ||
| 426 | input list<Integer> inIndices; | ||
| 427 | input String inName; | ||
| 428 | input DAE.Type expected_type; | ||
| 429 | input Boolean useConstValue "if true, use constant value in TYPED (if present)"; | ||
| 430 | output Option<DAE.Exp> outBinding; | ||
| 431 | algorithm | ||
| 432 | try | ||
| 433 | 942138 | outBinding := instBinding(inMod, varLst, expected_type, inIndices, inName, useConstValue); | |
| 434 | else | ||
| 435 | ✗ | Error.addMessage(Error.TYPE_ERROR, {inName, "enumeration type"}); | |
| 436 | ✗ | fail(); | |
| 437 | end try; | ||
| 438 | end instEnumerationBinding; | ||
| 439 | |||
| 440 | protected function instDistributionBinding | ||
| 441 | " | ||
| 442 | Author:Peter Aronsson, 2012 | ||
| 443 | |||
| 444 | Instantiates a distribution binding and retrieves the value. | ||
| 445 | " | ||
| 446 | input DAE.Mod inMod; | ||
| 447 | input list<DAE.Var> varLst; | ||
| 448 | input list<Integer> inIntegerLst; | ||
| 449 | input String inString; | ||
| 450 | input Boolean useConstValue "if true, use constant value in TYPED (if present)"; | ||
| 451 | output Option<DAE.Distribution> out; | ||
| 452 | algorithm | ||
| 453 | out := matchcontinue (inMod,inIntegerLst,inString) | ||
| 454 | local | ||
| 455 | DAE.Mod mod; | ||
| 456 | DAE.Exp name,params,paramNames; | ||
| 457 | list<Integer> index_list; | ||
| 458 | String bind_name; | ||
| 459 | DAE.Type ty; | ||
| 460 | Integer paramDim; | ||
| 461 | DAE.ComponentRef cr,crName,crParams; | ||
| 462 | Absyn.Path path; | ||
| 463 | |||
| 464 | //Record constructor | ||
| 465 | case (mod, index_list, bind_name) | ||
| 466 | algorithm | ||
| 467 |
2/14✗ Branch 1 not taken.
✓ Branch 2 taken 493460 times.
✓ Branch 3 taken 493460 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
493460 | SOME(DAE.CALL(path = path, expLst = {name,params, paramNames})) := instBinding(mod, varLst, distributionType, index_list, bind_name, useConstValue); |
| 468 | ✗ | true := AbsynUtil.pathEqual(path, Absyn.IDENT("Distribution")); | |
| 469 | ✗ | then | |
| 470 | SOME(DAE.DISTRIBUTION(name, params, paramNames)); | ||
| 471 | |||
| 472 | case (mod, index_list, bind_name) | ||
| 473 | algorithm | ||
| 474 |
2/14✗ Branch 1 not taken.
✓ Branch 2 taken 493460 times.
✓ Branch 3 taken 493460 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
493460 | SOME(DAE.RECORD(path = path, exps = {name,params, paramNames})) := instBinding(mod, varLst, distributionType, index_list, bind_name, useConstValue); |
| 475 | ✗ | true := AbsynUtil.pathEqual(path, Absyn.IDENT("Distribution")); | |
| 476 | ✗ | then | |
| 477 | SOME(DAE.DISTRIBUTION(name, params, paramNames)); | ||
| 478 | |||
| 479 | // Cref | ||
| 480 | case (mod, index_list, bind_name) | ||
| 481 | algorithm | ||
| 482 |
2/6✗ Branch 1 not taken.
✓ Branch 2 taken 493460 times.
✓ Branch 3 taken 493460 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
493460 | SOME(DAE.CREF(cr,ty)) := instBinding(mod, varLst, distributionType, index_list, bind_name, useConstValue); |
| 483 | ✗ | true := Types.isRecord(ty); | |
| 484 | ✗ | DAE.T_COMPLEX(varLst = _::DAE.TYPES_VAR(ty=DAE.T_ARRAY(dims={DAE.DIM_INTEGER(paramDim)}))::_) := ty; | |
| 485 | |||
| 486 | ✗ | crName := ComponentReference.crefPrependIdent(cr,"name",{},DAE.T_STRING_DEFAULT); | |
| 487 | ✗ | crParams := ComponentReference.crefPrependIdent(cr,"params",{},DAE.T_ARRAY(DAE.T_REAL_DEFAULT,{DAE.DIM_INTEGER(paramDim)})); | |
| 488 | ✗ | name := Expression.makeCrefExp(crName,DAE.T_STRING_DEFAULT); | |
| 489 | ✗ | params := Expression.makeCrefExp(crParams,DAE.T_ARRAY(DAE.T_REAL_DEFAULT,{DAE.DIM_INTEGER(paramDim)})); | |
| 490 | ✗ | paramNames := Expression.makeCrefExp(crParams,DAE.T_ARRAY(DAE.T_STRING_DEFAULT,{DAE.DIM_INTEGER(paramDim)})); | |
| 491 | ✗ | then | |
| 492 | SOME(DAE.DISTRIBUTION(name, params, paramNames)); | ||
| 493 | |||
| 494 | |||
| 495 | |||
| 496 | else NONE(); | ||
| 497 | |||
| 498 | end matchcontinue; | ||
| 499 | end instDistributionBinding; | ||
| 500 | |||
| 501 | protected function getUncertainFromExpOption | ||
| 502 | " | ||
| 503 | Author: Daniel Hedberg 2011-01 | ||
| 504 | |||
| 505 | Extracts the uncertainty value, as defined in DAE, from a DAE.Exp. | ||
| 506 | " | ||
| 507 | input Option<DAE.Exp> expOption; | ||
| 508 | output Option<DAE.Uncertainty> out; | ||
| 509 | algorithm | ||
| 510 | out := match expOption | ||
| 511 | case SOME(DAE.ENUM_LITERAL(name = Absyn.QUALIFIED(name = "Uncertainty", path = Absyn.IDENT("given")))) then SOME(DAE.GIVEN()); | ||
| 512 | case SOME(DAE.ENUM_LITERAL(name = Absyn.QUALIFIED(name = "Uncertainty", path = Absyn.IDENT("sought")))) then SOME(DAE.SOUGHT()); | ||
| 513 | case SOME(DAE.ENUM_LITERAL(name = Absyn.QUALIFIED(name = "Uncertainty", path = Absyn.IDENT("refine")))) then SOME(DAE.REFINE()); | ||
| 514 | case SOME(DAE.ENUM_LITERAL(name = Absyn.QUALIFIED(name = "Uncertainty", path = Absyn.IDENT("propagate")))) then SOME(DAE.PROPAGATE()); | ||
| 515 | else NONE(); | ||
| 516 | end match; | ||
| 517 | end getUncertainFromExpOption; | ||
| 518 | |||
| 519 | public function instModEquation | ||
| 520 | "This function adds the equation in the declaration | ||
| 521 | of a variable, if such an equation exists." | ||
| 522 | input DAE.ComponentRef inComponentRef; | ||
| 523 | input DAE.Type inType; | ||
| 524 | input DAE.Mod inMod; | ||
| 525 | input DAE.ElementSource inSource "the origin of the element"; | ||
| 526 | input Boolean inImpl; | ||
| 527 | output DAE.DAElist outDae; | ||
| 528 | algorithm | ||
| 529 | outDae:= matchcontinue (inType,inMod) | ||
| 530 | local | ||
| 531 | DAE.Type t; | ||
| 532 | DAE.DAElist dae; | ||
| 533 | DAE.Exp e,lhs; | ||
| 534 | DAE.Properties prop2; | ||
| 535 | Absyn.Exp aexp1,aexp2; | ||
| 536 | SCode.Equation scode; | ||
| 537 | Absyn.ComponentRef acr; | ||
| 538 | SourceInfo info; | ||
| 539 | DAE.ElementSource source; | ||
| 540 | |||
| 541 | // Record constructors are different | ||
| 542 | // If it's a constant binding, all fields will already be bound correctly. Don't return a DAE. | ||
| 543 | case (DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(_)), | ||
| 544 | DAE.MOD(binding = SOME(DAE.TYPED(_,SOME(_),DAE.PROP(_,DAE.C_CONST()),_)))) | ||
| 545 | then DAE.emptyDae; | ||
| 546 | |||
| 547 | // Special case if the dimensions of the expression is 0. | ||
| 548 | // If this is true, and it is instantiated normally, matching properties | ||
| 549 | // will result in error messages (Real[0] is not Real), so we handle it here. | ||
| 550 | case (_, DAE.MOD(binding = SOME(DAE.TYPED(properties = prop2)))) | ||
| 551 | algorithm | ||
| 552 |
1/10✓ Branch 1 taken 38400 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
38400 | DAE.T_ARRAY(dims = {DAE.DIM_INTEGER(0)}) := Types.getPropType(prop2); |
| 553 | then | ||
| 554 | DAE.emptyDae; | ||
| 555 | |||
| 556 | // Regular cases | ||
| 557 | case (_, DAE.MOD(binding = SOME(DAE.TYPED(e,_,prop2,aexp2)), info = info)) | ||
| 558 | algorithm | ||
| 559 | 38400 | t := Types.simplifyType(inType); | |
| 560 | 38400 | lhs := Expression.makeCrefExp(inComponentRef, t); | |
| 561 | 38400 | acr := ComponentReference.unelabCref(inComponentRef); | |
| 562 | 38400 | aexp1 := Absyn.CREF(acr); | |
| 563 | 38400 | scode := SCode.EQ_EQUALS(aexp1,aexp2,SCode.noComment,info); | |
| 564 | 38400 | source := ElementSource.addSymbolicTransformation(inSource,DAE.FLATTEN(scode,NONE())); | |
| 565 | 38400 | dae := InstSection.instEqEquation(lhs, DAE.PROP(inType,DAE.C_VAR()), e, prop2, source, SCode.NON_INITIAL(), inImpl, extraInfo=info); | |
| 566 | then | ||
| 567 | dae; | ||
| 568 | |||
| 569 | case (_, DAE.MOD(binding = NONE())) then DAE.emptyDae; | ||
| 570 | case (_, DAE.NOMOD()) then DAE.emptyDae; | ||
| 571 | case (_, DAE.REDECL()) then DAE.emptyDae; | ||
| 572 | |||
| 573 | else | ||
| 574 | algorithm | ||
| 575 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 576 | ✗ | Debug.trace("- InstBinding.instModEquation failed\n type: "); | |
| 577 | ✗ | Debug.trace(TypesDump.printTypeStr(inType)); | |
| 578 | ✗ | Debug.trace("\n cref: "); | |
| 579 | ✗ | Debug.trace(ComponentReferenceBasics.printComponentRefStr(inComponentRef)); | |
| 580 | ✗ | Debug.trace("\n mod:"); | |
| 581 | ✗ | Debug.traceln(Mod.printModStr(inMod)); | |
| 582 | ✗ | then | |
| 583 | fail(); | ||
| 584 | end matchcontinue; | ||
| 585 | end instModEquation; | ||
| 586 | |||
| 587 | public function makeBinding | ||
| 588 | "This function looks at the equation part of a modification, and | ||
| 589 | if there is a declaration equation builds a DAE.Binding for it." | ||
| 590 | input FCore.Cache inCache; | ||
| 591 | input FCore.Graph inEnv; | ||
| 592 | input SCode.Attributes inAttributes; | ||
| 593 | input DAE.Mod inMod; | ||
| 594 | input DAE.Type inType; | ||
| 595 | input DAE.Prefix inPrefix; | ||
| 596 | input String componentName; | ||
| 597 | input SourceInfo inInfo; | ||
| 598 | output FCore.Cache outCache; | ||
| 599 | output DAE.Binding outBinding; | ||
| 600 | algorithm | ||
| 601 | (outCache,outBinding) := matchcontinue (inCache,inAttributes,inMod,inType) | ||
| 602 | local | ||
| 603 | DAE.Type tp,e_tp; | ||
| 604 | DAE.Exp e_1,e,e_val_exp; | ||
| 605 | Option<Values.Value> e_val; | ||
| 606 | DAE.Const c; | ||
| 607 | String e_tp_str,tp_str,e_str,e_str_1,str; | ||
| 608 | FCore.Cache cache; | ||
| 609 | DAE.Properties prop; | ||
| 610 | DAE.Binding binding; | ||
| 611 | DAE.Mod startValueModification; | ||
| 612 | list<DAE.Var> complex_vars; | ||
| 613 | Absyn.Path tpath; | ||
| 614 | list<DAE.SubMod> sub_mods; | ||
| 615 | SourceInfo info; | ||
| 616 | Values.Value v; | ||
| 617 | |||
| 618 | // A record might have bindings from the class, use those if there is no modifier! | ||
| 619 | case (cache, _, DAE.NOMOD(), _) | ||
| 620 | algorithm | ||
| 621 |
4/4✓ Branch 1 taken 319356 times.
✓ Branch 2 taken 12956 times.
✓ Branch 3 taken 6823 times.
✓ Branch 4 taken 6133 times.
|
332312 | DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(path = tpath), |
| 622 | varLst = complex_vars) := Types.arrayElementType(inType); | ||
| 623 |
2/2✓ Branch 1 taken 4644 times.
✓ Branch 2 taken 1489 times.
|
6133 | true := Types.allHaveBindings(complex_vars); |
| 624 | 1489 | binding := makeRecordBinding(cache, inEnv, tpath, inType, complex_vars, {}, inInfo); | |
| 625 | 1489 | then | |
| 626 | (cache, binding); | ||
| 627 | |||
| 628 | 330823 | case (cache,_,DAE.NOMOD(),_) then (cache,DAE.UNBOUND()); | |
| 629 | |||
| 630 | case (_, _, DAE.REDECL(), _) | ||
| 631 | 60 | then makeBinding(inCache, inEnv, inAttributes, inMod.mod, inType, | |
| 632 | inPrefix, componentName, inInfo); | ||
| 633 | |||
| 634 | // adrpo: if the binding is missing for a parameter and | ||
| 635 | // the parameter has a start value modification, | ||
| 636 | // use that to create the binding as if we have | ||
| 637 | // a modification from outside it will be re-written. | ||
| 638 | // this fixes: | ||
| 639 | // Modelica.Electrical.Machines.Examples.SMEE_Generator | ||
| 640 | // (BUG: #1156 at https://openmodelica.org:8443/cb/issue/1156) | ||
| 641 | // and maybe a lot others. | ||
| 642 | case (cache,SCode.ATTR(variability = SCode.PARAM()),DAE.MOD(binding = NONE()),tp) | ||
| 643 | algorithm | ||
| 644 |
2/2✓ Branch 1 taken 124 times.
✓ Branch 2 taken 105 times.
|
229 | true := Types.getFixedVarAttributeParameterOrConstant(tp); |
| 645 | // this always succeeds but return NOMOD if there is no (start = x) | ||
| 646 | 105 | startValueModification := Mod.lookupCompModification(inMod, "start"); | |
| 647 | // make sure is NOT a DAE.NOMOD! | ||
| 648 |
2/2✓ Branch 1 taken 30 times.
✓ Branch 2 taken 75 times.
|
105 | false := Mod.isEmptyMod(startValueModification); |
| 649 | 75 | (cache,binding) := makeBinding(cache,inEnv,inAttributes,startValueModification,inType,inPrefix,componentName,inInfo); | |
| 650 | 75 | binding := DAEUtil.setBindingSource(binding, DAE.BINDING_FROM_START_VALUE()); | |
| 651 | |||
| 652 | // lochel: I moved the warning to the back end for now | ||
| 653 | // s = componentName; | ||
| 654 | // pre_str = PrefixUtil.printPrefixStr2(inPrefix); | ||
| 655 | // s = pre_str + s; | ||
| 656 | // str = DAEUtil.printBindingExpStr(binding); | ||
| 657 | // Error.addSourceMessage(Error.UNBOUND_PARAMETER_WITH_START_VALUE_WARNING, {s,str}, inInfo); | ||
| 658 | 75 | then | |
| 659 | (cache,binding); | ||
| 660 | |||
| 661 | // A record might have bindings for each component instead of a single | ||
| 662 | // binding for the whole record, in which case we need to assemble them into | ||
| 663 | // a binding. | ||
| 664 | case (cache, _, DAE.MOD(subModLst = sub_mods as _ :: _), _) | ||
| 665 | algorithm | ||
| 666 |
4/4✓ Branch 1 taken 26943 times.
✓ Branch 2 taken 5354 times.
✓ Branch 3 taken 2786 times.
✓ Branch 4 taken 2568 times.
|
32297 | DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(path = tpath), |
| 667 | varLst = complex_vars) := Types.arrayElementType(inType); | ||
| 668 | 2568 | binding := makeRecordBinding(cache, inEnv, tpath, inType, complex_vars, sub_mods, inInfo); | |
| 669 | 2562 | then | |
| 670 | (cache, binding); | ||
| 671 | |||
| 672 | 24063 | case (cache,_,DAE.MOD(binding = NONE()),_) then (cache,DAE.UNBOUND()); | |
| 673 | /* adrpo: CHECK! do we need this here? numerical values | ||
| 674 | case (cache,env,_,DAE.MOD(binding = SOME(DAE.TYPED(e,_,DAE.PROP(e_tp,_)))),tp,_,_) | ||
| 675 | algorithm | ||
| 676 | (e_1,_) = Types.matchType(e, e_tp, tp); | ||
| 677 | (cache,v,_) = Ceval.ceval(cache,env, e_1, false,NONE(), NONE(), Absyn.NO_MSG(),0); | ||
| 678 | then | ||
| 679 | (cache,DAE.VALBOUND(v, DAE.BINDING_FROM_DEFAULT_VALUE())); | ||
| 680 | */ | ||
| 681 | |||
| 682 | case (cache,_,DAE.MOD(binding = SOME(DAE.TYPED(e,SOME(v),prop,_))),e_tp) /* default */ | ||
| 683 | algorithm | ||
| 684 | 215571 | c := Types.propAllConst(prop); | |
| 685 | 215571 | tp := Types.getPropType(prop); | |
| 686 |
2/2✓ Branch 1 taken 180168 times.
✓ Branch 2 taken 35403 times.
|
215571 | false := Types.equivtypes(tp,e_tp); |
| 687 | 35403 | e_val_exp := ValuesUtil.valueExp(v, SOME(e)); | |
| 688 | // Handle bindings of the type Boolean b[Boolean]={true,false}, enumerations, and similar | ||
| 689 | // tp = Types.traverseType(tp, 1, Types.makeKnownDimensionsInteger); | ||
| 690 | // e_tp = Types.traverseType(e_tp, 1, Types.makeKnownDimensionsInteger); | ||
| 691 | 35403 | (e_1, _) := Types.matchType(e, tp, e_tp, false); | |
| 692 | 17207 | (e_1,_) := ExpressionSimplify.simplify(e_1); | |
| 693 | 17207 | (e_val_exp, _) := Types.matchType(e_val_exp, tp, e_tp, false); | |
| 694 | 17207 | (e_val_exp,_) := ExpressionSimplify.simplify(e_val_exp); | |
| 695 | 17207 | v := Ceval.cevalSimple(e_val_exp); | |
| 696 | e_val := SOME(v); | ||
| 697 | 17207 | then | |
| 698 | (cache,DAE.EQBOUND(e_1,e_val,c,DAE.BINDING_FROM_DEFAULT_VALUE())); | ||
| 699 | |||
| 700 | case (cache,_,DAE.MOD(binding = SOME(DAE.TYPED(e,e_val,prop,_))),e_tp) /* default */ | ||
| 701 | algorithm | ||
| 702 | 208319 | c := Types.propAllConst(prop); | |
| 703 | 208319 | tp := Types.getPropType(prop); | |
| 704 | // Handle bindings of the type Boolean b[Boolean]={true,false}, enumerations, and similar | ||
| 705 | // tp = Types.traverseType(tp, 1, Types.makeKnownDimensionsInteger); | ||
| 706 | // e_tp = Types.traverseType(e_tp, 1, Types.makeKnownDimensionsInteger); | ||
| 707 | 208319 | (e_1, _) := Types.matchType(e, tp, e_tp, false); | |
| 708 | 190123 | (e_1,_) := ExpressionSimplify.simplify(e_1); | |
| 709 | 190123 | then | |
| 710 | (cache,DAE.EQBOUND(e_1,e_val,c,DAE.BINDING_FROM_DEFAULT_VALUE())); | ||
| 711 | |||
| 712 | case (_,_,DAE.MOD(binding = SOME(DAE.TYPED(e,_,prop,_)), info = info),tp) | ||
| 713 | algorithm | ||
| 714 | 18196 | e_tp := Types.getPropType(prop); | |
| 715 |
2/2✓ Branch 0 taken 18196 times.
✓ Branch 1 taken 18196 times.
|
36392 | failure(Types.matchType(e, e_tp, tp, false)); |
| 716 | 18196 | e_tp_str := TypesDump.unparseTypeNoAttr(e_tp); | |
| 717 | 18196 | tp_str := TypesDump.unparseTypeNoAttr(tp); | |
| 718 | 18196 | e_str := ExpressionBasics.printExpStr(e); | |
| 719 | 18196 | e_str_1 := stringAppend("=", e_str); | |
| 720 | 18196 | str := PrefixUtil.printPrefixStrIgnoreNoPre(inPrefix) + "." + componentName; | |
| 721 | 18196 | Types.typeErrorSanityCheck(e_tp_str, tp_str, info); | |
| 722 | 18196 | Error.addSourceMessage(Error.MODIFIER_TYPE_MISMATCH_ERROR, {str,tp_str,e_str_1,e_tp_str}, info); | |
| 723 | 18196 | then | |
| 724 | fail(); | ||
| 725 | |||
| 726 | else | ||
| 727 | algorithm | ||
| 728 |
2/2✓ Branch 1 taken 18182 times.
✓ Branch 2 taken 14 times.
|
18196 | true := Flags.isSet(Flags.FAILTRACE); |
| 729 | 14 | Debug.traceln("- Inst.makeBinding failed on component:" + PrefixUtil.printPrefixStr(inPrefix) + "." + componentName); | |
| 730 | 14 | then | |
| 731 | fail(); | ||
| 732 | end matchcontinue; | ||
| 733 | end makeBinding; | ||
| 734 | |||
| 735 | public function makeRecordBinding | ||
| 736 | "Creates a binding for a record given a list of submodifiers. This is the case | ||
| 737 | when a record is given a binding by modifiers, ex: | ||
| 738 | |||
| 739 | record R | ||
| 740 | Real x; Real y; | ||
| 741 | end R; | ||
| 742 | |||
| 743 | constant R r(x = 2.0, y = 3.0); | ||
| 744 | |||
| 745 | This is translated to: | ||
| 746 | constant R r = R(2.0, 3.0); | ||
| 747 | |||
| 748 | This is needed when we assign a record to another record. | ||
| 749 | " | ||
| 750 | input FCore.Cache inCache; | ||
| 751 | input FCore.Graph inEnv; | ||
| 752 | input Absyn.Path inRecordName; | ||
| 753 | input DAE.Type inRecordType; | ||
| 754 | input list<DAE.Var> inRecordVars; | ||
| 755 | input list<DAE.SubMod> inMods; | ||
| 756 | input SourceInfo inInfo; | ||
| 757 | output DAE.Binding outBinding; | ||
| 758 | protected | ||
| 759 | list<DAE.Exp> accum_exps = {}; | ||
| 760 | list<Values.Value> accum_vals = {}; | ||
| 761 | list<String> accum_names = {}; | ||
| 762 | list<DAE.SubMod> mods = inMods; | ||
| 763 | Option<DAE.SubMod> opt_mod; | ||
| 764 | String name = "", scope, ty_str; | ||
| 765 | DAE.Type ty, ety; | ||
| 766 | DAE.Binding binding; | ||
| 767 | list<DAE.Dimension> dims; | ||
| 768 | DAE.Exp exp; | ||
| 769 | Values.Value val; | ||
| 770 | algorithm | ||
| 771 | 4057 | dims := TypesDump.getDimensions(inRecordType); | |
| 772 | |||
| 773 | try | ||
| 774 |
2/2✓ Branch 0 taken 33026 times.
✓ Branch 1 taken 4051 times.
|
37077 | for var in inRecordVars loop |
| 775 | 33026 | DAE.TYPES_VAR(name = name, ty = ty, binding = binding) := var; | |
| 776 | |||
| 777 | // Try to find a submod with the same name as the variable. | ||
| 778 | 33026 | (mods, opt_mod) := List.deleteMemberOnTrue(name, mods, InstUtil.isSubModNamed); | |
| 779 | |||
| 780 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 33026 times.
✓ Branch 2 taken 7461 times.
✓ Branch 3 taken 25565 times.
|
33026 | if isSome(opt_mod) then |
| 781 | // Found a submod, use its binding. | ||
| 782 | 25565 | ty := Types.liftArrayListDims(ty, dims); | |
| 783 | 25565 | (exp, val) := makeRecordBinding3(opt_mod, ty, inInfo); | |
| 784 | elseif DAEUtil.isBound(binding) then | ||
| 785 | // Couldn't find a submod, but variable has a binding already. | ||
| 786 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 7456 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7456 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 7453 times.
|
7456 | DAE.EQBOUND(exp = exp, evaluatedExp = SOME(val)) := binding; |
| 787 | else | ||
| 788 | // Couldn't find a submod, and the variable doesn't have a binding. | ||
| 789 | 5 | ety := Types.simplifyType(ty); | |
| 790 | 5 | ty := Types.liftArrayListDims(ty, dims); | |
| 791 | 5 | scope := FGraph.printGraphPathStr(inEnv); | |
| 792 | 5 | ty_str := TypesDump.printTypeStr(ty); | |
| 793 | 5 | exp := DAE.EMPTY(scope, DAE.CREF_IDENT(name, ety, {}), ety, ty_str); | |
| 794 | 5 | val := Values.EMPTY(scope, name, Types.typeToValue(ty), ty_str); | |
| 795 | end if; | ||
| 796 | |||
| 797 | 33020 | accum_exps := exp :: accum_exps; | |
| 798 | 33020 | accum_vals := val :: accum_vals; | |
| 799 | accum_names := name :: accum_names; | ||
| 800 | end for; | ||
| 801 | |||
| 802 | // Assemble the binding for the record. | ||
| 803 | 4051 | ety := Types.simplifyType(Types.arrayElementType(inRecordType)); | |
| 804 | 4051 | exp := DAE.CALL(inRecordName, listReverse(accum_exps), | |
| 805 | DAE.CALL_ATTR(ety, false, false, false, false, DAE.NORM_INLINE(), DAE.NO_TAIL(), DAE.NoReturn.RETURNS)); | ||
| 806 | 4051 | val := Values.RECORD(inRecordName, listReverse(accum_vals), listReverse(accum_names), -1); | |
| 807 | 4051 | (exp, val) := InstUtil.liftRecordBinding(inRecordType, exp, val); | |
| 808 | 4051 | outBinding := DAE.EQBOUND(exp, SOME(val), DAE.C_CONST(), DAE.BINDING_FROM_RECORD_SUBMODS()); | |
| 809 | else | ||
| 810 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
6 | if Flags.isSet(Flags.FAILTRACE) then |
| 811 | ✗ | Debug.traceln("- Inst.makeRecordBinding2 failed for " + | |
| 812 | AbsynUtil.pathString(inRecordName) + "." + name + "\n"); | ||
| 813 | end if; | ||
| 814 | 6 | fail(); | |
| 815 | end try; | ||
| 816 | end makeRecordBinding; | ||
| 817 | |||
| 818 | protected function makeRecordBinding3 | ||
| 819 | "Helper function to makeRecordBinding2. Fetches the binding expression and | ||
| 820 | value from an optional submod." | ||
| 821 | input Option<DAE.SubMod> inSubMod; | ||
| 822 | input DAE.Type inType; | ||
| 823 | input SourceInfo inInfo; | ||
| 824 | output DAE.Exp outExp; | ||
| 825 | output Values.Value outValue; | ||
| 826 | algorithm | ||
| 827 | (outExp, outValue) := matchcontinue inSubMod | ||
| 828 | local | ||
| 829 | DAE.Exp exp; | ||
| 830 | Values.Value val; | ||
| 831 | DAE.Type ty; | ||
| 832 | DAE.Ident ident; | ||
| 833 | String binding_str, expected_type_str, given_type_str; | ||
| 834 | |||
| 835 | // Array type and each prefix => return the expression and value. | ||
| 836 | case SOME(DAE.NAMEMOD(mod = DAE.MOD(eachPrefix = SCode.EACH(), binding = | ||
| 837 | SOME(DAE.TYPED(modifierAsExp = exp, modifierAsValue = SOME(val)))))) | ||
| 838 | then (exp, val); | ||
| 839 | |||
| 840 | // Scalar type and no each prefix => return the expression and value. | ||
| 841 | case SOME(DAE.NAMEMOD(mod = DAE.MOD(eachPrefix = SCode.NOT_EACH(), binding = | ||
| 842 | SOME(DAE.TYPED(modifierAsExp = exp, modifierAsValue = SOME(val), properties = DAE.PROP(type_ = ty)))))) | ||
| 843 | algorithm | ||
| 844 | 25275 | (exp, ty) := Types.matchType(exp, ty, inType, true); | |
| 845 | then | ||
| 846 | (exp, val); | ||
| 847 | |||
| 848 | // Scalar type and no each prefix => bindings given by expressions myRecord(v1 = inV1, v2 = inV2) | ||
| 849 | case SOME(DAE.NAMEMOD(mod = DAE.MOD(eachPrefix = SCode.NOT_EACH(), binding = | ||
| 850 | SOME(DAE.TYPED(modifierAsExp = exp, modifierAsValue = NONE(), properties = DAE.PROP(type_ = ty)))))) | ||
| 851 | algorithm | ||
| 852 | 32 | (exp, ty) := Types.matchType(exp, ty, inType, true); | |
| 853 | then | ||
| 854 | (exp, Values.OPTION(NONE())); | ||
| 855 | |||
| 856 | case SOME(DAE.NAMEMOD(ident = ident, mod = DAE.MOD(binding = | ||
| 857 | SOME(DAE.TYPED(modifierAsExp = exp, properties = DAE.PROP(type_ = ty)))))) | ||
| 858 | algorithm | ||
| 859 | ✗ | binding_str := ExpressionBasics.printExpStr(exp); | |
| 860 | ✗ | expected_type_str := TypesDump.unparseTypeNoAttr(inType); | |
| 861 | ✗ | given_type_str := TypesDump.unparseTypeNoAttr(ty); | |
| 862 | ✗ | Types.typeErrorSanityCheck(given_type_str, expected_type_str, inInfo); | |
| 863 | ✗ | Error.addSourceMessage(Error.VARIABLE_BINDING_TYPE_MISMATCH, | |
| 864 | {ident, binding_str, expected_type_str, given_type_str}, inInfo); | ||
| 865 | ✗ | then | |
| 866 | fail(); | ||
| 867 | |||
| 868 | end matchcontinue; | ||
| 869 | end makeRecordBinding3; | ||
| 870 | |||
| 871 | public function makeVariableBinding | ||
| 872 | "Returns a variable's bound expression." | ||
| 873 | input DAE.Type inType; | ||
| 874 | input DAE.Mod inMod; | ||
| 875 | input DAE.Const inConst; | ||
| 876 | input DAE.Prefix inPrefix; | ||
| 877 | input String inName; | ||
| 878 | output Option<DAE.Exp> outBinding; | ||
| 879 | protected | ||
| 880 | Option<DAE.EqMod> oeq_mod = Mod.modEquation(inMod); | ||
| 881 | DAE.Exp e, e2; | ||
| 882 | DAE.Properties p; | ||
| 883 | SourceInfo info; | ||
| 884 | DAE.Const c; | ||
| 885 | String e_str, et_str, bt_str; | ||
| 886 | algorithm | ||
| 887 | // No modifier => no binding. | ||
| 888 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 542966 times.
✓ Branch 2 taken 250132 times.
✓ Branch 3 taken 292834 times.
|
542966 | if isNone(oeq_mod) then |
| 889 | outBinding := NONE(); | ||
| 890 | 250132 | return; | |
| 891 | end if; | ||
| 892 | |||
| 893 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 292834 times.
|
292834 | SOME(DAE.TYPED(modifierAsExp = e, properties = p)) := oeq_mod; |
| 894 | |||
| 895 |
2/2✓ Branch 1 taken 34 times.
✓ Branch 2 taken 292800 times.
|
292834 | if Types.isExternalObject(inType) then |
| 896 | // For external objects the binding contains the constructor call. Return it as it is. | ||
| 897 | outBinding := SOME(e); | ||
| 898 | elseif Types.isEmptyArray(Types.getPropType(p)) then | ||
| 899 | // An empty array has unknown type, skip type matching. | ||
| 900 | outBinding := NONE(); | ||
| 901 | else | ||
| 902 | 292795 | info := Mod.getModInfo(inMod); | |
| 903 | |||
| 904 | // For normal variables, make sure the types match. | ||
| 905 | try | ||
| 906 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 292789 times.
|
292795 | (e2, DAE.PROP(constFlag = c)) := |
| 907 | Types.matchProp(e, p, DAE.PROP(inType, inConst), true); | ||
| 908 | else | ||
| 909 | // The types of the variable and binding are incompatible, print an error. | ||
| 910 | 6 | e_str := ExpressionBasics.printExpStr(e); | |
| 911 | 6 | et_str := TypesDump.unparseTypeNoAttr(inType); | |
| 912 | 6 | bt_str := TypesDump.unparseTypeNoAttr(Types.getPropType(p)); | |
| 913 | 6 | Types.typeErrorSanityCheck(et_str, bt_str, info); | |
| 914 | 6 | Error.addSourceMessageAndFail(Error.VARIABLE_BINDING_TYPE_MISMATCH, | |
| 915 | {inName, e_str, et_str, bt_str}, info); | ||
| 916 | end try; | ||
| 917 | |||
| 918 | // Check that the variability is compatible too. | ||
| 919 | 292789 | InstUtil.checkHigherVariability(inConst, c, inPrefix, inName, e, info); | |
| 920 | outBinding := SOME(e2); | ||
| 921 | end if; | ||
| 922 | end makeVariableBinding; | ||
| 923 | |||
| 924 | annotation(__OpenModelica_Interface="frontend"); | ||
| 925 | end InstBinding; | ||
| 926 |