OMCompiler/Compiler/FrontEnd/Types.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 Types | ||
| 37 | " file: Types.mo | ||
| 38 | package: Types | ||
| 39 | description: Type system | ||
| 40 | |||
| 41 | |||
| 42 | This file specifies the type system, as defined in the modelica specification. | ||
| 43 | It contains an MetaModelica Compiler (MMC) type called Type which defines types. | ||
| 44 | It also contains functions for determining subtyping etc. | ||
| 45 | |||
| 46 | There are a few known problems with this module. | ||
| 47 | It currently depends on SCode.Attributes, which in turn depends on Absyn.ArrayDim. | ||
| 48 | However, the only things used from those modules are constants that could be moved to their own modules. | ||
| 49 | |||
| 50 | " | ||
| 51 | |||
| 52 | public import ClassInf; | ||
| 53 | public import Absyn; | ||
| 54 | public import AbsynUtil; | ||
| 55 | public import DAE; | ||
| 56 | public import InstTypes; | ||
| 57 | public import TypesDump; | ||
| 58 | public import Values; | ||
| 59 | public import SCode; | ||
| 60 | |||
| 61 | protected type Binding = DAE.Binding; | ||
| 62 | protected type Const = DAE.Const; | ||
| 63 | protected type EqualityConstraint = DAE.EqualityConstraint; | ||
| 64 | protected type FuncArg = DAE.FuncArg; | ||
| 65 | protected type Properties = DAE.Properties; | ||
| 66 | protected type TupleConst = DAE.TupleConst; | ||
| 67 | protected type Type = DAE.Type; | ||
| 68 | protected type Var = DAE.Var; | ||
| 69 | protected type EqMod = DAE.EqMod; | ||
| 70 | |||
| 71 | protected import ComponentReference; | ||
| 72 | protected import ComponentReferenceBasics; | ||
| 73 | protected import Config; | ||
| 74 | protected import Dump; | ||
| 75 | protected import Debug; | ||
| 76 | protected import Error; | ||
| 77 | protected import Expression; | ||
| 78 | protected import ExpressionSimplify; | ||
| 79 | protected import Flags; | ||
| 80 | protected import List; | ||
| 81 | protected import Print; | ||
| 82 | protected import Util; | ||
| 83 | protected import System; | ||
| 84 | protected import ValuesDump; | ||
| 85 | protected import ValuesUtil; | ||
| 86 | protected import DAEUtil; | ||
| 87 | protected import MetaModelica.Dangerous.listReverseInPlace; | ||
| 88 | protected import ClassInfUtil; | ||
| 89 | protected import ExpressionBasics; | ||
| 90 | |||
| 91 | public function discreteType "Succeeds for all the discrete types, Integer, String, Boolean and enumeration." | ||
| 92 | input DAE.Type inType; | ||
| 93 | algorithm | ||
| 94 | ✗ | true := isDiscreteType(inType); | |
| 95 | end discreteType; | ||
| 96 | |||
| 97 | public function isDiscreteType | ||
| 98 | input DAE.Type inType; | ||
| 99 | output Boolean outIsDiscrete; | ||
| 100 | algorithm | ||
| 101 | outIsDiscrete := match inType | ||
| 102 | case DAE.T_INTEGER() then true; | ||
| 103 | case DAE.T_STRING() then true; | ||
| 104 | case DAE.T_BOOL() then true; | ||
| 105 | case DAE.T_CLOCK() then true; | ||
| 106 | case DAE.T_ENUMERATION() then true; | ||
| 107 | ✗ | case DAE.T_SUBTYPE_BASIC() then isDiscreteType(inType.complexType); | |
| 108 | else false; | ||
| 109 | end match; | ||
| 110 | end isDiscreteType; | ||
| 111 | |||
| 112 | public function propsAnd "Function for merging a list of properties, currently only working on DAE.PROP() and not TUPLE_DAE.PROP()." | ||
| 113 | input list<DAE.Properties> inProps; | ||
| 114 | output DAE.Properties outProp; | ||
| 115 | algorithm outProp := match inProps | ||
| 116 | local | ||
| 117 | Properties prop; | ||
| 118 | Const c,c2; | ||
| 119 | Type ty,ty2; | ||
| 120 | list<DAE.Properties> props; | ||
| 121 | |||
| 122 | case prop::{} then prop; | ||
| 123 | case (DAE.PROP(ty,c))::props | ||
| 124 | algorithm | ||
| 125 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 379 times.
|
379 | DAE.PROP(ty2,c2) := propsAnd(props); |
| 126 | 379 | c := constAnd(c,c2); | |
| 127 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 379 times.
|
379 | true := equivtypes(ty,ty2); |
| 128 | 379 | then | |
| 129 | DAE.PROP(ty,c); | ||
| 130 | end match; | ||
| 131 | end propsAnd; | ||
| 132 | |||
| 133 | public function makePropsNotConst | ||
| 134 | "returns the same Properties but with the const flag set to Var" | ||
| 135 | input DAE.Properties inProperties; | ||
| 136 | output DAE.Properties outProperties; | ||
| 137 | algorithm outProperties := match inProperties | ||
| 138 | local | ||
| 139 | Type t; | ||
| 140 | ✗ | case DAE.PROP(type_=t) then DAE.PROP(t,DAE.C_VAR()); | |
| 141 | end match; | ||
| 142 | end makePropsNotConst; | ||
| 143 | |||
| 144 | // stefan | ||
| 145 | public function getConstList | ||
| 146 | "retrieves a list of Consts from a list of Properties" | ||
| 147 | input list<DAE.Properties> inPropertiesList; | ||
| 148 | output list<DAE.Const> outConstList; | ||
| 149 | algorithm | ||
| 150 | outConstList := match inPropertiesList | ||
| 151 | local | ||
| 152 | Const c; | ||
| 153 | list<DAE.Const> ccdr; | ||
| 154 | list<DAE.Properties> pcdr; | ||
| 155 | TupleConst tc; | ||
| 156 | case {} then {}; | ||
| 157 | case DAE.PROP(constFlag=c) :: pcdr | ||
| 158 | algorithm | ||
| 159 | 3293 | ccdr := getConstList(pcdr); | |
| 160 | then | ||
| 161 | c :: ccdr; | ||
| 162 | case DAE.PROP_TUPLE(tupleConst=tc) :: pcdr | ||
| 163 | algorithm | ||
| 164 | ✗ | c := propertiesListToConst2(tc); | |
| 165 | ✗ | ccdr := getConstList(pcdr); | |
| 166 | then | ||
| 167 | c :: ccdr; | ||
| 168 | end match; | ||
| 169 | end getConstList; | ||
| 170 | |||
| 171 | |||
| 172 | public function propertiesListToConst "this function elaborates on a DAE.Properties and return the DAE.Const value." | ||
| 173 | input list<DAE.Properties> p; | ||
| 174 | output DAE.Const c; | ||
| 175 | algorithm | ||
| 176 | c := match p | ||
| 177 | local | ||
| 178 | list<DAE.Properties> pps; | ||
| 179 | Const c1,c2; | ||
| 180 | TupleConst tc1; | ||
| 181 | |||
| 182 | case {} then DAE.C_CONST(); | ||
| 183 | |||
| 184 | case (DAE.PROP(_,c1))::pps | ||
| 185 | algorithm | ||
| 186 | 4690 | c2 := propertiesListToConst(pps); | |
| 187 | 4690 | c1 := constAnd(c1, c2); | |
| 188 | then | ||
| 189 | c1; | ||
| 190 | |||
| 191 | case (DAE.PROP_TUPLE(_,tc1))::pps | ||
| 192 | algorithm | ||
| 193 | ✗ | c1 := propertiesListToConst2(tc1); | |
| 194 | ✗ | c2 := propertiesListToConst(pps); | |
| 195 | ✗ | c1 := constAnd(c1, c2); | |
| 196 | then | ||
| 197 | c1; | ||
| 198 | end match; | ||
| 199 | end propertiesListToConst; | ||
| 200 | |||
| 201 | protected function propertiesListToConst2 "" | ||
| 202 | input DAE.TupleConst t; | ||
| 203 | output DAE.Const c; | ||
| 204 | algorithm | ||
| 205 | c := match t | ||
| 206 | local | ||
| 207 | Const c1,c2; | ||
| 208 | list<TupleConst> tcxl; | ||
| 209 | TupleConst tc1; | ||
| 210 | |||
| 211 | case DAE.SINGLE_CONST(c1) then c1; | ||
| 212 | |||
| 213 | case DAE.TUPLE_CONST(tc1::tcxl) | ||
| 214 | algorithm | ||
| 215 | ✗ | c1 := propertiesListToConst2(tc1); | |
| 216 | ✗ | c2 := tupleConstListToConst(tcxl); | |
| 217 | ✗ | c1 := constAnd(c1, c2); | |
| 218 | then | ||
| 219 | c1; | ||
| 220 | end match; | ||
| 221 | end propertiesListToConst2; | ||
| 222 | |||
| 223 | public function tupleConstListToConst "" | ||
| 224 | input list<DAE.TupleConst> t; | ||
| 225 | output DAE.Const c; | ||
| 226 | algorithm | ||
| 227 | c := match t | ||
| 228 | local | ||
| 229 | TupleConst p1; | ||
| 230 | Const c1,c2; | ||
| 231 | list<TupleConst> tcxl; | ||
| 232 | |||
| 233 | case {} then DAE.C_CONST(); | ||
| 234 | |||
| 235 | case (DAE.SINGLE_CONST(c1))::tcxl | ||
| 236 | algorithm | ||
| 237 | 6097 | c2 := tupleConstListToConst(tcxl); | |
| 238 | 6097 | c1 := constAnd(c1, c2); | |
| 239 | then | ||
| 240 | c1; | ||
| 241 | |||
| 242 | case (p1 as DAE.TUPLE_CONST(_))::tcxl | ||
| 243 | algorithm | ||
| 244 | ✗ | c1 := propertiesListToConst2(p1); | |
| 245 | ✗ | c2 := tupleConstListToConst(tcxl); | |
| 246 | ✗ | c1 := constAnd(c1, c2); | |
| 247 | then | ||
| 248 | c1; | ||
| 249 | end match; | ||
| 250 | end tupleConstListToConst; | ||
| 251 | |||
| 252 | public function externalObjectType | ||
| 253 | "author: PA | ||
| 254 | Succeeds if type is ExternalObject" | ||
| 255 | input DAE.Type inType; | ||
| 256 | algorithm | ||
| 257 | () := match inType | ||
| 258 | case DAE.T_COMPLEX(complexClassType = ClassInf.EXTERNAL_OBJ(_)) then (); | ||
| 259 | end match; | ||
| 260 | end externalObjectType; | ||
| 261 | |||
| 262 | public function varBinding | ||
| 263 | input DAE.Var inVar; | ||
| 264 | output DAE.Binding outBinding; | ||
| 265 | algorithm | ||
| 266 | 212 | DAE.TYPES_VAR(binding = outBinding) := inVar; | |
| 267 | end varBinding; | ||
| 268 | |||
| 269 | public function varEqualName | ||
| 270 | input DAE.Var inVar1; | ||
| 271 | input DAE.Var inVar2; | ||
| 272 | output Boolean outEqual; | ||
| 273 | protected | ||
| 274 | String name1, name2; | ||
| 275 | algorithm | ||
| 276 | 234 | DAE.TYPES_VAR(name = name1) := inVar1; | |
| 277 | 234 | DAE.TYPES_VAR(name = name2) := inVar2; | |
| 278 |
2/4✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 234 times.
|
234 | outEqual := name1 == name2; |
| 279 | end varEqualName; | ||
| 280 | |||
| 281 | public function externalObjectConstructorType "author: PA | ||
| 282 | Succeeds if type is ExternalObject constructor function" | ||
| 283 | input DAE.Type inType; | ||
| 284 | algorithm | ||
| 285 | () := match inType | ||
| 286 | local Type tp; | ||
| 287 | case DAE.T_FUNCTION(funcResultType = tp) | ||
| 288 | algorithm | ||
| 289 | 3 | externalObjectType(tp); | |
| 290 | then (); | ||
| 291 | end match; | ||
| 292 | end externalObjectConstructorType; | ||
| 293 | |||
| 294 | public function simpleType "author: PA | ||
| 295 | Succeeds for all the builtin types, Integer, String, Real, Boolean" | ||
| 296 | input DAE.Type inType; | ||
| 297 | algorithm | ||
| 298 | ✗ | true := isSimpleType(inType); | |
| 299 | end simpleType; | ||
| 300 | |||
| 301 | public function isSimpleType | ||
| 302 | "Returns true for all the builtin types, Integer, String, Real, Boolean" | ||
| 303 | input DAE.Type inType; | ||
| 304 | output Boolean b; | ||
| 305 | algorithm | ||
| 306 | b := match inType | ||
| 307 | local DAE.Type t; | ||
| 308 | case DAE.T_REAL() then true; | ||
| 309 | case DAE.T_INTEGER() then true; | ||
| 310 | case DAE.T_STRING() then true; | ||
| 311 | case DAE.T_BOOL() then true; | ||
| 312 | // BTH | ||
| 313 | case DAE.T_CLOCK() then true; | ||
| 314 | case DAE.T_ENUMERATION() then true; | ||
| 315 | ✗ | case DAE.T_SUBTYPE_BASIC(complexType = t) then isSimpleType(t); | |
| 316 | ✗ | case DAE.T_FUNCTION(funcResultType = t) then isSimpleType(t); | |
| 317 | else false; | ||
| 318 | end match; | ||
| 319 | end isSimpleType; | ||
| 320 | |||
| 321 | public function isSimpleNumericType | ||
| 322 | "Returns true for simple numeric builtin types, Integer and Real" | ||
| 323 | input DAE.Type inType; | ||
| 324 | output Boolean b; | ||
| 325 | algorithm | ||
| 326 | b := match inType | ||
| 327 | local DAE.Type t; | ||
| 328 | case DAE.T_REAL() then true; | ||
| 329 | case DAE.T_INTEGER() then true; | ||
| 330 | ✗ | case DAE.T_SUBTYPE_BASIC(complexType = t) then isSimpleNumericType(t); | |
| 331 | ✗ | case DAE.T_FUNCTION(funcResultType = t) then isSimpleNumericType(t); | |
| 332 | else false; | ||
| 333 | end match; | ||
| 334 | end isSimpleNumericType; | ||
| 335 | |||
| 336 | public function isNumericType "This function checks if the element type is Numeric type or array of Numeric type." | ||
| 337 | input DAE.Type inType; | ||
| 338 | output Boolean outBool; | ||
| 339 | algorithm | ||
| 340 | outBool := match inType | ||
| 341 | local Type ty; | ||
| 342 | |||
| 343 | ✗ | case DAE.T_ARRAY(ty = ty) then isNumericType(ty); | |
| 344 | ✗ | case DAE.T_SUBTYPE_BASIC(complexType = ty) then isNumericType(ty); | |
| 345 | ✗ | case DAE.T_FUNCTION(funcResultType = ty) then isNumericType(ty); | |
| 346 | ✗ | else isSimpleNumericType(inType); | |
| 347 | |||
| 348 | end match; | ||
| 349 | end isNumericType; | ||
| 350 | |||
| 351 | public function isConnector | ||
| 352 | "Returns true if the given type is a connector type, otherwise false." | ||
| 353 | input DAE.Type inType; | ||
| 354 | output Boolean outIsConnector; | ||
| 355 | algorithm | ||
| 356 | outIsConnector := match inType | ||
| 357 | case DAE.T_COMPLEX(complexClassType = ClassInf.CONNECTOR()) then true; | ||
| 358 | case DAE.T_SUBTYPE_BASIC(complexClassType = ClassInf.CONNECTOR()) then true; | ||
| 359 | else false; | ||
| 360 | end match; | ||
| 361 | end isConnector; | ||
| 362 | |||
| 363 | public function isComplexConnector | ||
| 364 | "Returns true if the given type is a complex connector type, i.e. a connector | ||
| 365 | with components, otherwise false." | ||
| 366 | input DAE.Type inType; | ||
| 367 | output Boolean outIsComplexConnector; | ||
| 368 | algorithm | ||
| 369 | outIsComplexConnector := match inType | ||
| 370 | case DAE.T_COMPLEX(complexClassType = ClassInf.CONNECTOR()) then true; | ||
| 371 | else false; | ||
| 372 | end match; | ||
| 373 | end isComplexConnector; | ||
| 374 | |||
| 375 | public function isComplexExpandableConnector | ||
| 376 | "Returns true if the given type is an expandable connector, otherwise false." | ||
| 377 | input DAE.Type inType; | ||
| 378 | output Boolean outResult; | ||
| 379 | algorithm | ||
| 380 | outResult := match inType | ||
| 381 | case DAE.T_COMPLEX(complexClassType = | ||
| 382 | ClassInf.CONNECTOR(isExpandable = true)) then true; | ||
| 383 | case DAE.T_SUBTYPE_BASIC(complexClassType = | ||
| 384 | ClassInf.CONNECTOR(isExpandable = true)) then true; | ||
| 385 | else false; | ||
| 386 | end match; | ||
| 387 | end isComplexExpandableConnector; | ||
| 388 | |||
| 389 | public function isComplexType " | ||
| 390 | Author: BZ, 2008-11 | ||
| 391 | This function checks wheter a type is complex AND not extending a base type." | ||
| 392 | input DAE.Type ity; | ||
| 393 | output Boolean b; | ||
| 394 | algorithm | ||
| 395 | b := match ity | ||
| 396 | local Type ty; | ||
| 397 | 3413 | case DAE.T_SUBTYPE_BASIC(complexType = ty) then isComplexType(ty); | |
| 398 | 44 | case DAE.T_FUNCTION(funcResultType = ty) then isComplexType(ty); | |
| 399 | case DAE.T_COMPLEX(varLst = _::_) then true; // not derived from baseclass | ||
| 400 | else false; | ||
| 401 | end match; | ||
| 402 | end isComplexType; | ||
| 403 | |||
| 404 | public function isExternalObject "Returns true if type is COMPLEX and external object (ClassInf)" | ||
| 405 | input DAE.Type tp; | ||
| 406 | output Boolean b; | ||
| 407 | algorithm | ||
| 408 | b := match tp | ||
| 409 | case DAE.T_COMPLEX(complexClassType = ClassInf.EXTERNAL_OBJ(_)) then true; | ||
| 410 | else false; | ||
| 411 | end match; | ||
| 412 | end isExternalObject; | ||
| 413 | |||
| 414 | public function expTypetoTypesType | ||
| 415 | " Converts a DAE.Type to a DAE.Type | ||
| 416 | NOTE: This function should not be used in general, since it is not recommended to translate DAE.Type into DAE.Type." | ||
| 417 | input DAE.Type inType; | ||
| 418 | output DAE.Type oType; | ||
| 419 | algorithm | ||
| 420 | oType := matchcontinue inType | ||
| 421 | local | ||
| 422 | Type ty,tty; | ||
| 423 | Type at; | ||
| 424 | DAE.Dimensions ad; | ||
| 425 | DAE.Dimension dim; | ||
| 426 | list<DAE.Var> vars; | ||
| 427 | ClassInf.State CIS; | ||
| 428 | DAE.EqualityConstraint ec; | ||
| 429 | |||
| 430 | // convert just the array! | ||
| 431 | case DAE.T_ARRAY(at,{dim}) | ||
| 432 | algorithm | ||
| 433 | 669 | ty := expTypetoTypesType(at); | |
| 434 | 669 | tty := DAE.T_ARRAY(ty,{dim}); | |
| 435 | then | ||
| 436 | tty; | ||
| 437 | case DAE.T_ARRAY(at,dim::ad) | ||
| 438 | algorithm | ||
| 439 | 103 | ty := expTypetoTypesType(DAE.T_ARRAY(at,ad)); | |
| 440 | 103 | tty := DAE.T_ARRAY(ty,{dim}); | |
| 441 | then | ||
| 442 | tty; | ||
| 443 | |||
| 444 | case DAE.T_COMPLEX(CIS, vars, ec) | ||
| 445 | algorithm | ||
| 446 | 3 | vars := List.map(vars, convertFromExpToTypesVar); | |
| 447 | 3 | then | |
| 448 | DAE.T_COMPLEX(CIS, vars, ec, inType.usedExternally); | ||
| 449 | |||
| 450 | case DAE.T_SUBTYPE_BASIC(CIS, vars, ty, ec) | ||
| 451 | algorithm | ||
| 452 | ✗ | vars := List.map(vars, convertFromExpToTypesVar); | |
| 453 | ✗ | ty := expTypetoTypesType(ty); | |
| 454 | ✗ | then DAE.T_SUBTYPE_BASIC(CIS, vars, ty, ec); | |
| 455 | |||
| 456 | case DAE.T_METABOXED(ty) | ||
| 457 | algorithm | ||
| 458 | ✗ | ty := expTypetoTypesType(ty); | |
| 459 | ✗ | then DAE.T_METABOXED(ty); | |
| 460 | |||
| 461 | // the rest fall in line! | ||
| 462 | else inType; | ||
| 463 | |||
| 464 | end matchcontinue; | ||
| 465 | end expTypetoTypesType; | ||
| 466 | |||
| 467 | protected function convertFromExpToTypesVar "" | ||
| 468 | input DAE.Var inVar; | ||
| 469 | output DAE.Var outVar; | ||
| 470 | algorithm | ||
| 471 | outVar := inVar; | ||
| 472 | 7 | outVar.ty := expTypetoTypesType(inVar.ty); | |
| 473 | end convertFromExpToTypesVar; | ||
| 474 | |||
| 475 | public function isTuple "Returns true if type is TUPLE" | ||
| 476 | input DAE.Type tp; | ||
| 477 | output Boolean b; | ||
| 478 | algorithm | ||
| 479 | b := match tp | ||
| 480 | case DAE.T_TUPLE() then true; | ||
| 481 | else false; | ||
| 482 | end match; | ||
| 483 | end isTuple; | ||
| 484 | |||
| 485 | public function isMetaTuple "Returns true if type is TUPLE" | ||
| 486 | input DAE.Type tp; | ||
| 487 | output Boolean b; | ||
| 488 | algorithm | ||
| 489 | b := match tp | ||
| 490 | case DAE.T_METATUPLE() then true; | ||
| 491 | else false; | ||
| 492 | end match; | ||
| 493 | end isMetaTuple; | ||
| 494 | |||
| 495 | public function isRecord "Returns true if type is COMPLEX and a record (ClassInf)" | ||
| 496 | input DAE.Type tp; | ||
| 497 | output Boolean b; | ||
| 498 | algorithm | ||
| 499 | b := match tp | ||
| 500 | case DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(_)) then true; | ||
| 501 | else false; | ||
| 502 | end match; | ||
| 503 | end isRecord; | ||
| 504 | |||
| 505 | public function recordHasConstVar | ||
| 506 | "Returns true if an record has at least one component of type CONST. | ||
| 507 | Fails if input type ty is not an record." | ||
| 508 | input DAE.Type ty; | ||
| 509 | output Boolean hasConstType = false; | ||
| 510 | algorithm | ||
| 511 | () := match ty | ||
| 512 | case DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(_)) algorithm | ||
| 513 |
2/2✓ Branch 0 taken 24593 times.
✓ Branch 1 taken 8010 times.
|
32603 | for var in ty.varLst loop |
| 514 |
2/2✓ Branch 1 taken 24588 times.
✓ Branch 2 taken 5 times.
|
24593 | if DAEUtil.isConstVar(var) then |
| 515 | hasConstType := true; | ||
| 516 | break; | ||
| 517 | end if; | ||
| 518 | end for; | ||
| 519 | then(); | ||
| 520 | else algorithm | ||
| 521 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because input type is not a record."}); | |
| 522 | ✗ | then fail(); | |
| 523 | end match; | ||
| 524 | end recordHasConstVar; | ||
| 525 | |||
| 526 | public function getRecordPath "gets the record path" | ||
| 527 | input DAE.Type tp; | ||
| 528 | output Absyn.Path p; | ||
| 529 | algorithm | ||
| 530 | p := match tp | ||
| 531 | case DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(p)) | ||
| 532 | then p; | ||
| 533 | end match; | ||
| 534 | end getRecordPath; | ||
| 535 | |||
| 536 | public function isRecordWithOnlyReals "Returns true if type is a record only containing Reals" | ||
| 537 | input DAE.Type tp; | ||
| 538 | output Boolean b; | ||
| 539 | algorithm | ||
| 540 | b := match tp | ||
| 541 | local | ||
| 542 | list<DAE.Var> varLst; | ||
| 543 | |||
| 544 | case DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(_),varLst = varLst) | ||
| 545 | ✗ | then List.all(List.map(varLst, getVarType), isReal); | |
| 546 | |||
| 547 | // otherwise false | ||
| 548 | else false; | ||
| 549 | end match; | ||
| 550 | end isRecordWithOnlyReals; | ||
| 551 | |||
| 552 | public function getVarType "Return the Type of a Var" | ||
| 553 | input DAE.Var v; | ||
| 554 | output DAE.Type tp; | ||
| 555 | algorithm | ||
| 556 | tp := match v | ||
| 557 | case DAE.TYPES_VAR(ty = tp) then tp; | ||
| 558 | else | ||
| 559 | algorithm | ||
| 560 | ✗ | Error.addMessage(Error.INTERNAL_ERROR, {"Types.getVarType failed"}); | |
| 561 | ✗ | then fail(); | |
| 562 | end match; | ||
| 563 | end getVarType; | ||
| 564 | |||
| 565 | public function varIsVariable | ||
| 566 | input DAE.Var v; | ||
| 567 | output Boolean b; | ||
| 568 | algorithm | ||
| 569 | b := match v | ||
| 570 | case DAE.TYPES_VAR(attributes=DAE.ATTR(variability=SCode.VAR())) then true; | ||
| 571 | case DAE.TYPES_VAR(attributes=DAE.ATTR(variability=SCode.DISCRETE())) then true; | ||
| 572 | else false; | ||
| 573 | end match; | ||
| 574 | end varIsVariable; | ||
| 575 | |||
| 576 | public function isReal "Returns true if type is Real" | ||
| 577 | input DAE.Type tp; | ||
| 578 | output Boolean res; | ||
| 579 | algorithm | ||
| 580 | 29991494 | res := isScalarReal(arrayElementType(tp)); | |
| 581 | end isReal; | ||
| 582 | |||
| 583 | public function isScalarReal | ||
| 584 | input DAE.Type inType; | ||
| 585 | output Boolean outIsScalarReal; | ||
| 586 | algorithm | ||
| 587 | outIsScalarReal := match inType | ||
| 588 | local | ||
| 589 | Type ty; | ||
| 590 | |||
| 591 | case DAE.T_REAL() then true; | ||
| 592 | 11 | case DAE.T_SUBTYPE_BASIC(complexType = ty) then isScalarReal(ty); | |
| 593 | else false; | ||
| 594 | end match; | ||
| 595 | end isScalarReal; | ||
| 596 | |||
| 597 | public function isRealOrSubTypeReal " | ||
| 598 | Author BZ 2008-05 | ||
| 599 | This function verifies if it is some kind of a Real type we are working with." | ||
| 600 | input DAE.Type inType; | ||
| 601 | output Boolean b; | ||
| 602 | protected | ||
| 603 | Boolean lb1, lb2; | ||
| 604 | algorithm | ||
| 605 | 29513909 | lb1 := isReal(inType); | |
| 606 | 29513909 | lb2 := equivtypes(inType, DAE.T_REAL_DEFAULT); | |
| 607 | 29513909 | b := lb1 or lb2; | |
| 608 | end isRealOrSubTypeReal; | ||
| 609 | |||
| 610 | public function isIntegerOrSubTypeInteger " | ||
| 611 | Author BZ 2009-02 | ||
| 612 | This function verifies if it is some kind of an Integer type we are working with." | ||
| 613 | input DAE.Type inType; | ||
| 614 | output Boolean b; | ||
| 615 | protected | ||
| 616 | Boolean lb1, lb2; | ||
| 617 | algorithm | ||
| 618 | 54236 | lb1 := isInteger(inType); | |
| 619 | 54236 | lb2 := equivtypes(inType, DAE.T_INTEGER_DEFAULT); | |
| 620 | 54236 | b := lb1 or lb2; | |
| 621 | end isIntegerOrSubTypeInteger; | ||
| 622 | |||
| 623 | public function isEnumerationOrSubTypeEnumeration " | ||
| 624 | This function verifies if it is some kind of an Enumeration type we are working with." | ||
| 625 | input DAE.Type inType; | ||
| 626 | output Boolean b; | ||
| 627 | protected | ||
| 628 | Boolean lb1, lb2; | ||
| 629 | algorithm | ||
| 630 | ✗ | lb1 := isEnumeration(inType); | |
| 631 | ✗ | lb2 := equivtypes(inType, DAE.T_ENUMERATION_DEFAULT); | |
| 632 | ✗ | b := lb1 or lb2; | |
| 633 | end isEnumerationOrSubTypeEnumeration; | ||
| 634 | |||
| 635 | protected function isClockOrSubTypeClock1 | ||
| 636 | input DAE.Type inType; | ||
| 637 | output Boolean b; | ||
| 638 | protected | ||
| 639 | Boolean lb1, lb2, lb3; | ||
| 640 | algorithm | ||
| 641 | 172184 | lb1 := isClock(inType); | |
| 642 | 172184 | lb2 := equivtypes(inType, DAE.T_CLOCK_DEFAULT); | |
| 643 | 172184 | lb3 := not equivtypes(inType, DAE.T_UNKNOWN_DEFAULT); | |
| 644 |
3/4✓ Branch 0 taken 171459 times.
✓ Branch 1 taken 725 times.
✓ Branch 2 taken 171459 times.
✗ Branch 3 not taken.
|
172184 | b := lb1 or (lb2 and lb3); |
| 645 | end isClockOrSubTypeClock1; | ||
| 646 | |||
| 647 | public function isClockOrSubTypeClock | ||
| 648 | input DAE.Type inType; | ||
| 649 | output Boolean b; | ||
| 650 | algorithm | ||
| 651 | b := match inType | ||
| 652 | local | ||
| 653 | DAE.Type ty; | ||
| 654 | case DAE.T_FUNCTION(funcResultType=ty) | ||
| 655 | ✗ | then isClockOrSubTypeClock1(ty); | |
| 656 | 172184 | else isClockOrSubTypeClock1(inType); | |
| 657 | end match; | ||
| 658 | end isClockOrSubTypeClock; | ||
| 659 | |||
| 660 | public function isBooleanOrSubTypeBoolean | ||
| 661 | "@author: adrpo | ||
| 662 | This function verifies if it is some kind of a Boolean type we are working with." | ||
| 663 | input DAE.Type inType; | ||
| 664 | output Boolean b; | ||
| 665 | protected | ||
| 666 | Boolean lb1, lb2; | ||
| 667 | algorithm | ||
| 668 | 259 | lb1 := isBoolean(inType); | |
| 669 | 259 | lb2 := equivtypes(inType, DAE.T_BOOL_DEFAULT); | |
| 670 | 259 | b := lb1 or lb2; | |
| 671 | end isBooleanOrSubTypeBoolean; | ||
| 672 | |||
| 673 | public function isStringOrSubTypeString | ||
| 674 | "@author: adrpo | ||
| 675 | This function verifies if it is some kind of a String type we are working with." | ||
| 676 | input DAE.Type inType; | ||
| 677 | output Boolean b; | ||
| 678 | protected | ||
| 679 | Boolean lb1, lb2; | ||
| 680 | algorithm | ||
| 681 | 4 | lb1 := isString(inType); | |
| 682 | 4 | lb2 := equivtypes(inType, DAE.T_STRING_DEFAULT); | |
| 683 | 4 | b := lb1 or lb2; | |
| 684 | end isStringOrSubTypeString; | ||
| 685 | |||
| 686 | public function isIntegerOrRealOrSubTypeOfEither | ||
| 687 | "Checks if a type is either some Integer or Real type." | ||
| 688 | input DAE.Type t; | ||
| 689 | output Boolean b; | ||
| 690 | algorithm | ||
| 691 | b := match t | ||
| 692 | case _ guard isRealOrSubTypeReal(t) then true; | ||
| 693 | case _ guard isIntegerOrSubTypeInteger(t) then true; | ||
| 694 | else false; | ||
| 695 | end match; | ||
| 696 | end isIntegerOrRealOrSubTypeOfEither; | ||
| 697 | |||
| 698 | public function isIntegerOrRealOrBooleanOrSubTypeOfEither | ||
| 699 | "Checks if a type is either some Integer or Real type." | ||
| 700 | input DAE.Type t; | ||
| 701 | output Boolean b; | ||
| 702 | algorithm | ||
| 703 | b := match t | ||
| 704 | case _ guard isRealOrSubTypeReal(t) then true; | ||
| 705 | case _ guard isIntegerOrSubTypeInteger(t) then true; | ||
| 706 | case _ guard isBooleanOrSubTypeBoolean(t) then true; | ||
| 707 | else false; | ||
| 708 | end match; | ||
| 709 | end isIntegerOrRealOrBooleanOrSubTypeOfEither; | ||
| 710 | |||
| 711 | public function isClock | ||
| 712 | input DAE.Type tp; | ||
| 713 | output Boolean res; | ||
| 714 | algorithm | ||
| 715 | 172184 | res := isScalarClock(arrayElementType(tp)); | |
| 716 | end isClock; | ||
| 717 | |||
| 718 | public function isScalarClock | ||
| 719 | input DAE.Type inType; | ||
| 720 | output Boolean res; | ||
| 721 | algorithm | ||
| 722 | res := match inType | ||
| 723 | local | ||
| 724 | Type ty; | ||
| 725 | case DAE.T_CLOCK() then true; | ||
| 726 | ✗ | case DAE.T_SUBTYPE_BASIC(complexType = ty) then isScalarClock(ty); | |
| 727 | else false; | ||
| 728 | end match; | ||
| 729 | end isScalarClock; | ||
| 730 | |||
| 731 | public function isInteger "Returns true if type is Integer" | ||
| 732 | input DAE.Type tp; | ||
| 733 | output Boolean res; | ||
| 734 | algorithm | ||
| 735 | 231941 | res := isScalarInteger(arrayElementType(tp)); | |
| 736 | end isInteger; | ||
| 737 | |||
| 738 | public function isScalarInteger | ||
| 739 | input DAE.Type inType; | ||
| 740 | output Boolean outIsScalarInteger; | ||
| 741 | algorithm | ||
| 742 | outIsScalarInteger := match inType | ||
| 743 | local | ||
| 744 | Type ty; | ||
| 745 | |||
| 746 | case DAE.T_INTEGER() then true; | ||
| 747 | 2 | case DAE.T_SUBTYPE_BASIC(complexType = ty) then isScalarInteger(ty); | |
| 748 | else false; | ||
| 749 | end match; | ||
| 750 | end isScalarInteger; | ||
| 751 | |||
| 752 | public function isBoolean "Returns true if type is Boolean" | ||
| 753 | input DAE.Type tp; | ||
| 754 | output Boolean res; | ||
| 755 | algorithm | ||
| 756 | 27374 | res := isScalarBoolean(arrayElementType(tp)); | |
| 757 | end isBoolean; | ||
| 758 | |||
| 759 | public function isScalarBoolean | ||
| 760 | input DAE.Type inType; | ||
| 761 | output Boolean outIsScalarBoolean; | ||
| 762 | algorithm | ||
| 763 | outIsScalarBoolean := match inType | ||
| 764 | local | ||
| 765 | Type ty; | ||
| 766 | |||
| 767 | case DAE.T_BOOL() then true; | ||
| 768 | ✗ | case DAE.T_SUBTYPE_BASIC(complexType = ty) then isScalarBoolean(ty); | |
| 769 | else false; | ||
| 770 | end match; | ||
| 771 | end isScalarBoolean; | ||
| 772 | |||
| 773 | public function integerOrReal "author: PA | ||
| 774 | Succeeds for the builtin types Integer and Real | ||
| 775 | (including classes extending the basetype Integer or Real)." | ||
| 776 | input DAE.Type inType; | ||
| 777 | algorithm | ||
| 778 | () := match inType | ||
| 779 | local Type tp; | ||
| 780 | case DAE.T_REAL() then (); | ||
| 781 | case DAE.T_INTEGER() then (); | ||
| 782 | case DAE.T_SUBTYPE_BASIC(complexType = tp) | ||
| 783 | algorithm | ||
| 784 | ✗ | integerOrReal(tp); | |
| 785 | then (); | ||
| 786 | end match; | ||
| 787 | end integerOrReal; | ||
| 788 | |||
| 789 | public function isNonscalarArray | ||
| 790 | "Returns true if Type is an nonscalar array (array of arrays)." | ||
| 791 | input DAE.Type inType; | ||
| 792 | input DAE.Dimensions inDims; | ||
| 793 | output Boolean outBoolean; | ||
| 794 | algorithm | ||
| 795 | outBoolean := matchcontinue (inType,inDims) | ||
| 796 | local | ||
| 797 | Type t; | ||
| 798 | list<Type> tys; | ||
| 799 | Boolean b; | ||
| 800 | // several (at least 2) dimensions means array! | ||
| 801 | case (_, _::_::_) then true; | ||
| 802 | // if the type is an array, then is an array | ||
| 803 | case (DAE.T_ARRAY(),_) then true; | ||
| 804 | // if is a type extending basic type | ||
| 805 | ✗ | case (DAE.T_SUBTYPE_BASIC(complexType = t),_) then isNonscalarArray(t, {}); | |
| 806 | case (DAE.T_TUPLE(types = tys), _) | ||
| 807 | algorithm | ||
| 808 | ✗ | b := List.applyAndFold1(tys, boolOr, isNonscalarArray, {}, false); | |
| 809 | then | ||
| 810 | b; | ||
| 811 | else false; | ||
| 812 | end matchcontinue; | ||
| 813 | end isNonscalarArray; | ||
| 814 | |||
| 815 | public function isArray | ||
| 816 | "Returns true if the given type is an array type." | ||
| 817 | input DAE.Type inType; | ||
| 818 | output Boolean outIsArray; | ||
| 819 | algorithm | ||
| 820 | outIsArray := match inType | ||
| 821 | case DAE.T_ARRAY() then true; | ||
| 822 | 196 | case DAE.T_SUBTYPE_BASIC() then isArray(inType.complexType); | |
| 823 | 5 | case DAE.T_FUNCTION() then isArray(inType.funcResultType); | |
| 824 | else false; | ||
| 825 | end match; | ||
| 826 | end isArray; | ||
| 827 | |||
| 828 | public function isEmptyArray | ||
| 829 | input DAE.Type inType; | ||
| 830 | output Boolean outBoolean; | ||
| 831 | algorithm | ||
| 832 | outBoolean := match inType | ||
| 833 | case DAE.T_ARRAY(dims = {DAE.DIM_INTEGER(0)}) then true; | ||
| 834 | else false; | ||
| 835 | end match; | ||
| 836 | end isEmptyArray; | ||
| 837 | |||
| 838 | public function isString "Return true if Type is the builtin String type." | ||
| 839 | input DAE.Type inType; | ||
| 840 | output Boolean outBoolean; | ||
| 841 | algorithm | ||
| 842 | outBoolean := match inType | ||
| 843 | case DAE.T_STRING() then true; | ||
| 844 | else false; | ||
| 845 | end match; | ||
| 846 | end isString; | ||
| 847 | |||
| 848 | public function isEnumeration "Return true if Type is the enumeration type." | ||
| 849 | input DAE.Type inType; | ||
| 850 | output Boolean outBoolean; | ||
| 851 | algorithm | ||
| 852 | outBoolean := match arrayElementType(inType) | ||
| 853 | case DAE.T_ENUMERATION() then true; | ||
| 854 | else false; | ||
| 855 | end match; | ||
| 856 | end isEnumeration; | ||
| 857 | |||
| 858 | public function isArrayOrString "Return true if Type is array or the builtin String type." | ||
| 859 | input DAE.Type inType; | ||
| 860 | output Boolean outBoolean; | ||
| 861 | algorithm | ||
| 862 | outBoolean := match inType | ||
| 863 | local Type ty; | ||
| 864 | case ty guard isArray(ty) then true; | ||
| 865 | case ty guard isString(ty) then true; | ||
| 866 | else false; | ||
| 867 | end match; | ||
| 868 | end isArrayOrString; | ||
| 869 | |||
| 870 | public function numberOfDimensions "Return the number of dimensions of a Type." | ||
| 871 | input DAE.Type inType; | ||
| 872 | output Integer outInteger; | ||
| 873 | algorithm | ||
| 874 | outInteger := match inType | ||
| 875 | local | ||
| 876 | Integer n; | ||
| 877 | Type t; | ||
| 878 | DAE.Dimensions dims; | ||
| 879 | |||
| 880 | case DAE.T_ARRAY(ty = t, dims = dims) | ||
| 881 | algorithm | ||
| 882 | 4075882 | n := numberOfDimensions(t); | |
| 883 | 4075882 | n := n + listLength(dims); | |
| 884 | then | ||
| 885 | n; | ||
| 886 | case DAE.T_SUBTYPE_BASIC(complexType = t) | ||
| 887 | algorithm | ||
| 888 | 32 | n := numberOfDimensions(t); | |
| 889 | then n; | ||
| 890 | else 0; | ||
| 891 | end match; | ||
| 892 | end numberOfDimensions; | ||
| 893 | |||
| 894 | public function dimensionsKnown | ||
| 895 | "Returns true if the dimensions of the type is known." | ||
| 896 | input DAE.Type inType; | ||
| 897 | output Boolean outRes; | ||
| 898 | algorithm | ||
| 899 | outRes := match inType | ||
| 900 | local | ||
| 901 | DAE.Dimension d; | ||
| 902 | DAE.Dimensions dims; | ||
| 903 | Type tp; | ||
| 904 | |||
| 905 | case DAE.T_ARRAY(dims = d::dims, ty = tp) guard Expression.dimensionKnown(d) and dimensionsKnown(DAE.T_ARRAY(tp, dims)) | ||
| 906 | then | ||
| 907 | true; | ||
| 908 | |||
| 909 | case DAE.T_ARRAY(dims = {}, ty = tp) guard dimensionsKnown(tp) | ||
| 910 | then | ||
| 911 | true; | ||
| 912 | |||
| 913 | case DAE.T_ARRAY() | ||
| 914 | then false; | ||
| 915 | |||
| 916 | case DAE.T_SUBTYPE_BASIC(complexType = tp) | ||
| 917 | ✗ | then dimensionsKnown(tp); | |
| 918 | |||
| 919 | else true; | ||
| 920 | end match; | ||
| 921 | end dimensionsKnown; | ||
| 922 | |||
| 923 | public function getDimensionSizes "Return the dimension sizes of a Type." | ||
| 924 | input DAE.Type inType; | ||
| 925 | output list<Integer> outIntegerLst; | ||
| 926 | algorithm | ||
| 927 | outIntegerLst := matchcontinue inType | ||
| 928 | local | ||
| 929 | list<Integer> res; | ||
| 930 | DAE.Dimension d; | ||
| 931 | DAE.Dimensions dims; | ||
| 932 | Integer i; | ||
| 933 | Type tp; | ||
| 934 | |||
| 935 | case DAE.T_ARRAY(dims = d::dims,ty = tp) | ||
| 936 | algorithm | ||
| 937 | 15151 | i := Expression.dimensionSize(d); | |
| 938 | 14966 | res := getDimensionSizes(DAE.T_ARRAY(tp, dims)); | |
| 939 | then | ||
| 940 | (i :: res); | ||
| 941 | |||
| 942 | case DAE.T_ARRAY(dims = _::dims, ty = tp) | ||
| 943 | algorithm | ||
| 944 | 185 | res := getDimensionSizes(DAE.T_ARRAY(tp, dims)); | |
| 945 | then | ||
| 946 | (0 :: res); | ||
| 947 | |||
| 948 | case DAE.T_ARRAY(dims = {},ty = tp) | ||
| 949 | algorithm | ||
| 950 | 14913 | res := getDimensionSizes(tp); | |
| 951 | then | ||
| 952 | res; | ||
| 953 | |||
| 954 | case DAE.T_SUBTYPE_BASIC(complexType=tp) | ||
| 955 | 56 | then getDimensionSizes(tp); | |
| 956 | |||
| 957 | else | ||
| 958 | algorithm | ||
| 959 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 380501 times.
|
380501 | false := arrayType(inType); |
| 960 | then | ||
| 961 | {}; | ||
| 962 | end matchcontinue; | ||
| 963 | end getDimensionSizes; | ||
| 964 | |||
| 965 | public function getDimensionProduct "Return the dimension sizes of a Type." | ||
| 966 | input DAE.Type inType; | ||
| 967 | output Integer sz; | ||
| 968 | algorithm | ||
| 969 | sz := match inType | ||
| 970 | local | ||
| 971 | DAE.Dimensions dims; | ||
| 972 | Type tp; | ||
| 973 | |||
| 974 | case DAE.T_ARRAY(dims = dims,ty = tp) | ||
| 975 |
4/4✓ Branch 0 taken 82107 times.
✓ Branch 1 taken 75776 times.
✓ Branch 2 taken 82107 times.
✓ Branch 3 taken 75776 times.
|
157883 | then product(Expression.dimensionSize(d) for d in dims) * getDimensionProduct(tp); |
| 976 | |||
| 977 | case DAE.T_SUBTYPE_BASIC(complexType=tp) | ||
| 978 | ✗ | then getDimensionProduct(tp); | |
| 979 | |||
| 980 | else | ||
| 981 | algorithm | ||
| 982 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1432965 times.
|
1432965 | false := arrayType(inType); |
| 983 | then 1; | ||
| 984 | end match; | ||
| 985 | end getDimensionProduct; | ||
| 986 | |||
| 987 | public function getDimensionNth | ||
| 988 | input DAE.Type inType; | ||
| 989 | input Integer inDim; | ||
| 990 | output DAE.Dimension outDimension; | ||
| 991 | algorithm | ||
| 992 | outDimension := matchcontinue(inType, inDim) | ||
| 993 | local | ||
| 994 | DAE.Dimension dim; | ||
| 995 | DAE.Type t; | ||
| 996 | Integer d, dc; | ||
| 997 | DAE.Dimensions dims; | ||
| 998 | |||
| 999 | case (DAE.T_ARRAY(dims = dims), d) | ||
| 1000 | algorithm | ||
| 1001 | 7267 | dim := listGet(dims, d); | |
| 1002 | then | ||
| 1003 | dim; | ||
| 1004 | |||
| 1005 | case (DAE.T_ARRAY(ty = t, dims = dims), d) | ||
| 1006 | algorithm | ||
| 1007 | 762 | dc := listLength(dims); | |
| 1008 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 762 times.
|
762 | true := (d > dc); |
| 1009 | 762 | then | |
| 1010 | getDimensionNth(t, d - dc); | ||
| 1011 | |||
| 1012 | case (DAE.T_SUBTYPE_BASIC(complexType = t), d) | ||
| 1013 | 4 | then getDimensionNth(t, d); | |
| 1014 | |||
| 1015 | end matchcontinue; | ||
| 1016 | end getDimensionNth; | ||
| 1017 | |||
| 1018 | public function setDimensionNth | ||
| 1019 | "Sets the nth dimension of an array type to the given dimension." | ||
| 1020 | input DAE.Type inType; | ||
| 1021 | input DAE.Dimension inDim; | ||
| 1022 | input Integer inDimNth; | ||
| 1023 | output DAE.Type outType; | ||
| 1024 | algorithm | ||
| 1025 | outType := match(inType, inDimNth) | ||
| 1026 | local | ||
| 1027 | DAE.Dimension dim; | ||
| 1028 | DAE.Type ty; | ||
| 1029 | |||
| 1030 | case (DAE.T_ARRAY(dims = {_}, ty = ty), 1) | ||
| 1031 | 69 | then DAE.T_ARRAY(ty, {inDim}); | |
| 1032 | |||
| 1033 | case (DAE.T_ARRAY(dims = {dim}, ty = ty), _) | ||
| 1034 | algorithm | ||
| 1035 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | true := inDimNth > 1; |
| 1036 | 2 | ty := setDimensionNth(ty, inDim, inDimNth - 1); | |
| 1037 | 2 | then | |
| 1038 | DAE.T_ARRAY(ty, {dim}); | ||
| 1039 | |||
| 1040 | end match; | ||
| 1041 | end setDimensionNth; | ||
| 1042 | |||
| 1043 | public function valuesToVars "Translates a list of Values.Value to a Var list, using a list | ||
| 1044 | of identifiers as component names. | ||
| 1045 | Used e.g. when retrieving the type of a record value." | ||
| 1046 | input list<Values.Value> inValuesValueLst; | ||
| 1047 | input list<DAE.Ident> inExpIdentLst; | ||
| 1048 | output list<DAE.Var> outVarLst; | ||
| 1049 | algorithm | ||
| 1050 | outVarLst := matchcontinue (inValuesValueLst,inExpIdentLst) | ||
| 1051 | local | ||
| 1052 | Type tp; | ||
| 1053 | list<DAE.Var> rest; | ||
| 1054 | Values.Value v; | ||
| 1055 | list<Values.Value> vs; | ||
| 1056 | String id; | ||
| 1057 | list<String> ids; | ||
| 1058 | |||
| 1059 | case ({},{}) then {}; | ||
| 1060 | case ((v :: vs),(id :: ids)) | ||
| 1061 | algorithm | ||
| 1062 | 113659 | tp := typeOfValue(v); | |
| 1063 | 113659 | rest := valuesToVars(vs, ids); | |
| 1064 | 113659 | then | |
| 1065 | (DAE.TYPES_VAR(id, DAE.dummyAttrVar, tp, DAE.UNBOUND(), false, NONE()) :: rest); | ||
| 1066 | |||
| 1067 | else | ||
| 1068 | algorithm | ||
| 1069 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 1070 | ✗ | Debug.trace("-values_to_vars failed\n"); | |
| 1071 | ✗ | then | |
| 1072 | fail(); | ||
| 1073 | end matchcontinue; | ||
| 1074 | end valuesToVars; | ||
| 1075 | |||
| 1076 | public function typeOfValue "author: PA | ||
| 1077 | Returns the type of a Values.Value. | ||
| 1078 | Some information is lost in the translation, like attributes | ||
| 1079 | of the builtin type." | ||
| 1080 | input Values.Value inValue; | ||
| 1081 | output DAE.Type outType; | ||
| 1082 | algorithm | ||
| 1083 | outType := matchcontinue inValue | ||
| 1084 | local | ||
| 1085 | Type tp; | ||
| 1086 | Integer dim1,index; | ||
| 1087 | Values.Value v; | ||
| 1088 | list<Values.Value> vs,vl; | ||
| 1089 | list<DAE.Type> ts; | ||
| 1090 | list<DAE.Var> vars; | ||
| 1091 | String str; | ||
| 1092 | Absyn.Path cname,path,utPath; | ||
| 1093 | list<String> ids; | ||
| 1094 | list<DAE.Exp> explist; | ||
| 1095 | Values.Value valType; | ||
| 1096 | |||
| 1097 | |||
| 1098 | ✗ | case Values.EMPTY(ty = valType) then typeOfValue(valType); | |
| 1099 | |||
| 1100 | case Values.INTEGER() then (DAE.T_INTEGER_DEFAULT); | ||
| 1101 | case Values.REAL() then (DAE.T_REAL_DEFAULT); | ||
| 1102 | case Values.STRING() then (DAE.T_STRING_DEFAULT); | ||
| 1103 | case Values.BOOL() then (DAE.T_BOOL_DEFAULT); | ||
| 1104 | case Values.ENUM_LITERAL(name = path, index = index) | ||
| 1105 | algorithm | ||
| 1106 | 1996 | path := AbsynUtil.pathPrefix(path); | |
| 1107 | 1996 | then DAE.T_ENUMERATION(SOME(index), path, {}, {}, {}); | |
| 1108 | |||
| 1109 | case Values.ARRAY(valueLst = (v :: vs)) | ||
| 1110 | algorithm | ||
| 1111 | 1746 | tp := typeOfValue(v); | |
| 1112 | 1746 | dim1 := listLength((v :: vs)); | |
| 1113 | 3492 | then | |
| 1114 | DAE.T_ARRAY(tp, {DAE.DIM_INTEGER(dim1)}); | ||
| 1115 | |||
| 1116 | case Values.ARRAY(valueLst = ({})) | ||
| 1117 | algorithm | ||
| 1118 | then | ||
| 1119 | DAE.T_ARRAY(DAE.T_UNKNOWN_DEFAULT, {DAE.DIM_INTEGER(0)}); | ||
| 1120 | |||
| 1121 | case Values.TUPLE(valueLst = vs) | ||
| 1122 | algorithm | ||
| 1123 | ✗ | ts := List.map(vs, typeOfValue); | |
| 1124 | ✗ | then DAE.T_TUPLE(ts,NONE()); | |
| 1125 | |||
| 1126 | case Values.RECORD(record_ = cname,orderd = vl,comp = ids, index = -1) | ||
| 1127 | algorithm | ||
| 1128 | 1899 | vars := valuesToVars(vl, ids); | |
| 1129 | 1899 | then DAE.T_COMPLEX(ClassInf.RECORD(cname),vars,NONE(), false); | |
| 1130 | |||
| 1131 | // MetaModelica Uniontype | ||
| 1132 | case Values.RECORD(record_ = cname,orderd = vl,comp = ids, index = index) | ||
| 1133 | algorithm | ||
| 1134 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 92283 times.
|
92283 | true := index >= 0; |
| 1135 | 92283 | vars := valuesToVars(vl, ids); | |
| 1136 | 92283 | utPath := AbsynUtil.stripLast(cname); | |
| 1137 | 92283 | then DAE.T_METARECORD(cname, utPath, {} /* typeVar? */, index, vars, false /*We simply do not know...*/); | |
| 1138 | |||
| 1139 | // MetaModelica list type | ||
| 1140 | case Values.LIST(vl) | ||
| 1141 | algorithm | ||
| 1142 | 22203 | explist := List.map(vl, function ValuesUtil.valueExp(originalExp=NONE())); | |
| 1143 | 22203 | ts := List.map(vl, typeOfValue); | |
| 1144 | 22203 | (_,tp) := listMatchSuperType(explist, ts, true); | |
| 1145 | 22203 | tp := boxIfUnboxedType(tp); | |
| 1146 | 22203 | then DAE.T_METALIST(tp); | |
| 1147 | |||
| 1148 | case Values.OPTION(NONE()) | ||
| 1149 | algorithm | ||
| 1150 | tp := DAE.T_METAOPTION(DAE.T_UNKNOWN_DEFAULT); | ||
| 1151 | then tp; | ||
| 1152 | |||
| 1153 | case Values.OPTION(SOME(v)) | ||
| 1154 | algorithm | ||
| 1155 | 1303 | tp := boxIfUnboxedType(typeOfValue(v)); | |
| 1156 | 1303 | tp := DAE.T_METAOPTION(tp); | |
| 1157 | then tp; | ||
| 1158 | |||
| 1159 | case Values.META_TUPLE(valueLst = vs) | ||
| 1160 | algorithm | ||
| 1161 | 19278 | ts := List.mapMap(vs, typeOfValue, boxIfUnboxedType); | |
| 1162 | 19278 | then DAE.T_METATUPLE(ts); | |
| 1163 | |||
| 1164 | case Values.META_ARRAY(valueLst = (v :: _)) | ||
| 1165 | algorithm | ||
| 1166 | ✗ | tp := boxIfUnboxedType(typeOfValue(v)); | |
| 1167 | ✗ | tp := DAE.T_METAARRAY(tp); | |
| 1168 | then tp; | ||
| 1169 | |||
| 1170 | case Values.META_ARRAY(valueLst = {}) | ||
| 1171 | algorithm | ||
| 1172 | tp := DAE.T_METAARRAY(DAE.T_UNKNOWN_DEFAULT); | ||
| 1173 | then tp; | ||
| 1174 | |||
| 1175 | case Values.META_BOX(v) | ||
| 1176 | algorithm | ||
| 1177 | ✗ | tp := typeOfValue(v); | |
| 1178 | ✗ | then boxIfUnboxedType(tp); | |
| 1179 | |||
| 1180 | case Values.NORETCALL() then DAE.T_NORETCALL_DEFAULT; | ||
| 1181 | |||
| 1182 | case Values.CODE(A=Absyn.C_TYPENAME()) | ||
| 1183 | then DAE.T_CODE(DAE.C_TYPENAME()); | ||
| 1184 | |||
| 1185 | case Values.CODE(A=Absyn.C_VARIABLENAME()) | ||
| 1186 | then DAE.T_CODE(DAE.C_VARIABLENAME()); | ||
| 1187 | |||
| 1188 | case Values.CODE(A=Absyn.C_EXPRESSION()) | ||
| 1189 | then DAE.T_CODE(DAE.C_EXPRESSION()); | ||
| 1190 | |||
| 1191 | case Values.CODE(A=Absyn.C_MODIFICATION()) | ||
| 1192 | then DAE.T_CODE(DAE.C_MODIFICATION()); | ||
| 1193 | |||
| 1194 | case v | ||
| 1195 | algorithm | ||
| 1196 | ✗ | str := "- Types.typeOfValue failed: " + ValuesDump.valString(v); | |
| 1197 | ✗ | Error.addMessage(Error.INTERNAL_ERROR, {str}); | |
| 1198 | ✗ | then | |
| 1199 | fail(); | ||
| 1200 | end matchcontinue; | ||
| 1201 | end typeOfValue; | ||
| 1202 | |||
| 1203 | public function basicType "Test whether a type is one of the builtin types." | ||
| 1204 | input DAE.Type inType; | ||
| 1205 | output Boolean outBoolean; | ||
| 1206 | algorithm | ||
| 1207 | outBoolean := match inType | ||
| 1208 | case DAE.T_INTEGER() then true; | ||
| 1209 | case DAE.T_REAL() then true; | ||
| 1210 | case DAE.T_STRING() then true; | ||
| 1211 | case DAE.T_BOOL() then true; | ||
| 1212 | // BTH | ||
| 1213 | case DAE.T_CLOCK() then true; | ||
| 1214 | case DAE.T_ENUMERATION() then true; | ||
| 1215 | else false; | ||
| 1216 | end match; | ||
| 1217 | end basicType; | ||
| 1218 | |||
| 1219 | public function extendsBasicType "Test whether a type extends one of the builtin types." | ||
| 1220 | input DAE.Type inType; | ||
| 1221 | output Boolean outBoolean; | ||
| 1222 | algorithm | ||
| 1223 | outBoolean := match inType | ||
| 1224 | case DAE.T_SUBTYPE_BASIC() then true; | ||
| 1225 | else false; | ||
| 1226 | end match; | ||
| 1227 | end extendsBasicType; | ||
| 1228 | |||
| 1229 | public function derivedBasicType | ||
| 1230 | "Returns the actual type of a type extending one of the builtin types." | ||
| 1231 | input DAE.Type inType; | ||
| 1232 | output DAE.Type outType; | ||
| 1233 | algorithm | ||
| 1234 | outType := match inType | ||
| 1235 | 1 | case DAE.T_SUBTYPE_BASIC() then derivedBasicType(inType.complexType); | |
| 1236 | else inType; | ||
| 1237 | end match; | ||
| 1238 | end derivedBasicType; | ||
| 1239 | |||
| 1240 | public function arrayType "Test whether a type is an array type." | ||
| 1241 | input DAE.Type inType; | ||
| 1242 | output Boolean outBoolean; | ||
| 1243 | algorithm | ||
| 1244 | outBoolean := match inType | ||
| 1245 | case DAE.T_ARRAY() then true; | ||
| 1246 | else false; | ||
| 1247 | end match; | ||
| 1248 | end arrayType; | ||
| 1249 | |||
| 1250 | public function setVarInput "Sets a DAE.Var to input" | ||
| 1251 | input DAE.Var var; | ||
| 1252 | output DAE.Var outV; | ||
| 1253 | protected | ||
| 1254 | DAE.Attributes attrs; | ||
| 1255 | algorithm | ||
| 1256 | outV := var; | ||
| 1257 | ✗ | attrs := outV.attributes; | |
| 1258 | ✗ | attrs.direction := Absyn.INPUT(); | |
| 1259 | ✗ | outV.attributes := attrs; | |
| 1260 | |||
| 1261 | // outV.attributes.direction := Absyn.INPUT(); | ||
| 1262 | end setVarInput; | ||
| 1263 | |||
| 1264 | public function setVarDefaultInput "Sets a DAE.Var to input" | ||
| 1265 | input DAE.Var var; | ||
| 1266 | output DAE.Var outV; | ||
| 1267 | protected | ||
| 1268 | DAE.Attributes attrs; | ||
| 1269 | algorithm | ||
| 1270 | outV := var; | ||
| 1271 | |||
| 1272 | 32334 | attrs := outV.attributes; | |
| 1273 | 32334 | attrs.connectorType := DAE.NON_CONNECTOR(); | |
| 1274 | attrs.variability := SCode.VAR(); | ||
| 1275 | attrs.direction := Absyn.INPUT(); | ||
| 1276 | attrs.innerOuter := Absyn.NOT_INNER_OUTER(); | ||
| 1277 | attrs.visibility := SCode.PUBLIC(); | ||
| 1278 | 32334 | outV.attributes := attrs; | |
| 1279 | |||
| 1280 | /* | ||
| 1281 | outV.attributes.connectorType := DAE.NON_CONNECTOR(); | ||
| 1282 | outV.attributes.variability := SCode.VAR(); | ||
| 1283 | outV.attributes.direction := Absyn.INPUT(); | ||
| 1284 | outV.attributes.innerOuter := Absyn.NOT_INNER_OUTER(); | ||
| 1285 | outV.attributes.visibility := SCode.PUBLIC(); | ||
| 1286 | */ | ||
| 1287 | end setVarDefaultInput; | ||
| 1288 | |||
| 1289 | public function setVarProtected "Sets a DAE.Var to input" | ||
| 1290 | input DAE.Var var; | ||
| 1291 | output DAE.Var outV; | ||
| 1292 | protected | ||
| 1293 | DAE.Attributes attrs; | ||
| 1294 | algorithm | ||
| 1295 | outV := var; | ||
| 1296 | 1324 | attrs := outV.attributes; | |
| 1297 | 1324 | attrs.visibility := SCode.PROTECTED(); | |
| 1298 | 1324 | outV.attributes := attrs; | |
| 1299 | // outV.attributes.visibility := SCode.PROTECTED(); | ||
| 1300 | end setVarProtected; | ||
| 1301 | |||
| 1302 | protected function setVarType "Sets a DAE.Var's type" | ||
| 1303 | input DAE.Var var; | ||
| 1304 | input DAE.Type ty; | ||
| 1305 | output DAE.Var outV = var; | ||
| 1306 | algorithm | ||
| 1307 | 668441 | outV.ty := ty; | |
| 1308 | end setVarType; | ||
| 1309 | |||
| 1310 | public function semiEquivTypes | ||
| 1311 | "This function checks whether two types are semi-equal... | ||
| 1312 | With 'semi' we mean that they have the same base type, and if both are arrays | ||
| 1313 | the numbers of dimensions are equal, not necessarily equal dimension-sizes." | ||
| 1314 | input DAE.Type inType1; | ||
| 1315 | input DAE.Type inType2; | ||
| 1316 | output Boolean outEquiv; | ||
| 1317 | protected | ||
| 1318 | DAE.Type ty1, ty2; | ||
| 1319 | list<DAE.Dimension> dims1, dims2; | ||
| 1320 | algorithm | ||
| 1321 | ✗ | if arrayType(inType1) and arrayType(inType2) then | |
| 1322 | ✗ | (ty1, dims1) := TypesDump.flattenArrayType(inType1); | |
| 1323 | ✗ | (ty2, dims2) := TypesDump.flattenArrayType(inType2); | |
| 1324 | ✗ | outEquiv := equivtypes(inType1, inType2) and listLength(dims1) == listLength(dims2); | |
| 1325 | elseif not arrayType(inType1) and not arrayType(inType2) then | ||
| 1326 | ✗ | outEquiv := equivtypes(inType1, inType2); | |
| 1327 | else | ||
| 1328 | outEquiv := false; | ||
| 1329 | end if; | ||
| 1330 | end semiEquivTypes; | ||
| 1331 | |||
| 1332 | public function equivtypes "This is the type equivalence function. It is defined in terms of | ||
| 1333 | the subtype function. Two types are considered equivalent if they | ||
| 1334 | are subtypes of each other." | ||
| 1335 | input DAE.Type t1; | ||
| 1336 | input DAE.Type t2; | ||
| 1337 | output Boolean outBoolean; | ||
| 1338 | algorithm | ||
| 1339 |
3/4✓ Branch 1 taken 29736617 times.
✓ Branch 2 taken 651886 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 29736617 times.
|
30388503 | outBoolean := subtype(t1, t2) and subtype(t2, t1); |
| 1340 | end equivtypes; | ||
| 1341 | |||
| 1342 | public function equivtypesOrRecordSubtypeOf | ||
| 1343 | "Like equivtypes but accepts non-typeconverted records as well (for connections)." | ||
| 1344 | input DAE.Type t1; | ||
| 1345 | input DAE.Type t2; | ||
| 1346 | output Boolean outBoolean; | ||
| 1347 | algorithm | ||
| 1348 |
3/4✓ Branch 1 taken 80419 times.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 80419 times.
|
80421 | outBoolean := subtype(t1, t2, false /* Allow record names to differ */) and subtype(t2, t1, false); |
| 1349 | end equivtypesOrRecordSubtypeOf; | ||
| 1350 | |||
| 1351 | public function subtype "Is the first type a subtype of the second type? | ||
| 1352 | This function specifies the rules for subtyping in Modelica." | ||
| 1353 | input DAE.Type inType1; | ||
| 1354 | input DAE.Type inType2; | ||
| 1355 | input Boolean requireRecordNamesEqual = true; | ||
| 1356 | output Boolean outBoolean; | ||
| 1357 | algorithm | ||
| 1358 | outBoolean := matchcontinue (inType1, inType2) | ||
| 1359 | local | ||
| 1360 | Boolean res, b1, b2; | ||
| 1361 | String l1,l2; | ||
| 1362 | list<DAE.Var> els1,els2; | ||
| 1363 | Absyn.Path p1,p2; | ||
| 1364 | DAE.Type t1,t2,tp2,tp1; | ||
| 1365 | ClassInf.State st1,st2; | ||
| 1366 | list<DAE.Type> type_list1,type_list2,tList1,tList2; | ||
| 1367 | list<String> names1, names2; | ||
| 1368 | DAE.Dimension dim1,dim2; | ||
| 1369 | DAE.Dimensions dlst1, dlst2; | ||
| 1370 | list<DAE.FuncArg> farg1,farg2; | ||
| 1371 | DAE.CodeType c1,c2; | ||
| 1372 | |||
| 1373 | case (DAE.T_ANYTYPE(), _) then true; | ||
| 1374 | case (_, DAE.T_ANYTYPE()) then true; | ||
| 1375 | case (DAE.T_INTEGER(), DAE.T_INTEGER()) then true; | ||
| 1376 | case (DAE.T_REAL(), DAE.T_REAL()) then true; | ||
| 1377 | case (DAE.T_STRING(), DAE.T_STRING()) then true; | ||
| 1378 | case (DAE.T_BOOL(), DAE.T_BOOL()) then true; | ||
| 1379 | // BTH | ||
| 1380 | case (DAE.T_CLOCK(), DAE.T_CLOCK()) then true; | ||
| 1381 | |||
| 1382 | case (DAE.T_ENUMERATION(names = {}), DAE.T_ENUMERATION()) then true; | ||
| 1383 | case (DAE.T_ENUMERATION(), DAE.T_ENUMERATION(names = {})) then true; | ||
| 1384 | |||
| 1385 | case (DAE.T_ENUMERATION(names = names1), | ||
| 1386 | DAE.T_ENUMERATION(names = names2)) | ||
| 1387 | algorithm | ||
| 1388 | 39216 | res := List.isEqualOnTrue(names1, names2, stringEq); | |
| 1389 | then | ||
| 1390 | res; | ||
| 1391 | |||
| 1392 | case (DAE.T_ARRAY(dims = dlst1 as _::_::_, ty = t1), | ||
| 1393 | DAE.T_ARRAY(dims = dlst2 as _::_::_, ty = t2)) | ||
| 1394 | algorithm | ||
| 1395 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6120 times.
|
6120 | true := Expression.dimsEqual(dlst1, dlst2); |
| 1396 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6120 times.
|
6120 | true := subtype(t1, t2, requireRecordNamesEqual); |
| 1397 | then | ||
| 1398 | true; | ||
| 1399 | |||
| 1400 | // try dims as list vs. dims as tree | ||
| 1401 | // T_ARRAY(a::b::c) vs. T_ARRAY(a, T_ARRAY(b, T_ARRAY(c))) | ||
| 1402 | case (DAE.T_ARRAY(dims = {dim1}, ty = t1), | ||
| 1403 | DAE.T_ARRAY(dims = dim2::(dlst2 as _::_), ty = t2)) | ||
| 1404 | algorithm | ||
| 1405 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 292 times.
|
292 | true := Expression.dimensionsEqual(dim1, dim2); |
| 1406 |
2/2✓ Branch 2 taken 44 times.
✓ Branch 3 taken 248 times.
|
292 | true := subtype(t1, DAE.T_ARRAY(t2, dlst2), requireRecordNamesEqual); |
| 1407 | then | ||
| 1408 | true; | ||
| 1409 | |||
| 1410 | // try subtype of dimension list vs. dimension tree | ||
| 1411 | case (DAE.T_ARRAY(dims = dim1::(dlst1 as _::_), ty = t1), | ||
| 1412 | DAE.T_ARRAY(dims = {dim2}, ty = t2)) | ||
| 1413 | algorithm | ||
| 1414 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 504 times.
|
504 | true := Expression.dimensionsEqual(dim1, dim2); |
| 1415 |
2/2✓ Branch 2 taken 22 times.
✓ Branch 3 taken 482 times.
|
504 | true := subtype(DAE.T_ARRAY(t1, dlst1), t2, requireRecordNamesEqual); |
| 1416 | then | ||
| 1417 | true; | ||
| 1418 | |||
| 1419 | case (DAE.T_ARRAY(ty = t1),DAE.T_ARRAY(dims = {DAE.DIM_UNKNOWN()}, ty = t2)) | ||
| 1420 | algorithm | ||
| 1421 |
2/2✓ Branch 1 taken 229733 times.
✓ Branch 2 taken 8777 times.
|
238510 | true := subtype(t1, t2, requireRecordNamesEqual); |
| 1422 | then | ||
| 1423 | true; | ||
| 1424 | |||
| 1425 | case (DAE.T_ARRAY(dims = {DAE.DIM_UNKNOWN()}, ty = t1),DAE.T_ARRAY(ty = t2)) | ||
| 1426 | algorithm | ||
| 1427 |
2/2✓ Branch 1 taken 107783 times.
✓ Branch 2 taken 27911 times.
|
135694 | true := subtype(t1, t2, requireRecordNamesEqual); |
| 1428 | then | ||
| 1429 | true; | ||
| 1430 | |||
| 1431 | case (DAE.T_ARRAY(dims = {DAE.DIM_EXP()}, ty = t1), | ||
| 1432 | DAE.T_ARRAY(dims = {DAE.DIM_EXP()}, ty = t2)) | ||
| 1433 | algorithm | ||
| 1434 | /* HUGE TODO: FIXME: After MSL is updated? */ | ||
| 1435 | // true = ExpressionBasics.expEqual(e1,e2); | ||
| 1436 |
2/2✓ Branch 1 taken 43 times.
✓ Branch 2 taken 116 times.
|
159 | true := subtype(t1, t2, requireRecordNamesEqual); |
| 1437 | then | ||
| 1438 | true; | ||
| 1439 | |||
| 1440 | case (DAE.T_ARRAY(ty = t1), | ||
| 1441 | DAE.T_ARRAY(dims = {DAE.DIM_EXP()}, ty = t2)) | ||
| 1442 | algorithm | ||
| 1443 |
2/2✓ Branch 1 taken 188 times.
✓ Branch 2 taken 3 times.
|
191 | true := subtype(t1, t2, requireRecordNamesEqual); |
| 1444 | then | ||
| 1445 | true; | ||
| 1446 | |||
| 1447 | case (DAE.T_ARRAY(dims = {DAE.DIM_EXP()}, ty = t1), | ||
| 1448 | DAE.T_ARRAY(ty = t2)) | ||
| 1449 | algorithm | ||
| 1450 |
2/2✓ Branch 1 taken 279 times.
✓ Branch 2 taken 5 times.
|
284 | true := subtype(t1, t2, requireRecordNamesEqual); |
| 1451 | then | ||
| 1452 | true; | ||
| 1453 | |||
| 1454 | // Array | ||
| 1455 | case (DAE.T_ARRAY(dims = {dim1}, ty = t1),DAE.T_ARRAY(dims = {dim2}, ty = t2)) | ||
| 1456 | algorithm | ||
| 1457 | /* | ||
| 1458 | true = boolOr(Expression.dimensionsKnownAndEqual(dim1, dim2), | ||
| 1459 | Expression.dimensionsEqualAllowZero(dim1, dim2)); | ||
| 1460 | */ | ||
| 1461 |
2/2✓ Branch 1 taken 335212 times.
✓ Branch 2 taken 389657 times.
|
724869 | true := Expression.dimensionsKnownAndEqual(dim1, dim2); |
| 1462 |
2/2✓ Branch 1 taken 59787 times.
✓ Branch 2 taken 329870 times.
|
389657 | true := subtype(t1, t2, requireRecordNamesEqual); |
| 1463 | then | ||
| 1464 | true; | ||
| 1465 | |||
| 1466 | // External objects use a nominal type system | ||
| 1467 | case (DAE.T_COMPLEX(complexClassType = ClassInf.EXTERNAL_OBJ(p1)), | ||
| 1468 | DAE.T_COMPLEX(complexClassType = ClassInf.EXTERNAL_OBJ(p2))) | ||
| 1469 | 644 | then | |
| 1470 | AbsynUtil.pathEqual(p1,p2); | ||
| 1471 | |||
| 1472 | // Complex type | ||
| 1473 | case (DAE.T_COMPLEX(complexClassType = st1,varLst = els1), | ||
| 1474 | DAE.T_COMPLEX(complexClassType = st2,varLst = els2)) | ||
| 1475 | algorithm | ||
| 1476 |
3/4✓ Branch 1 taken 14260 times.
✓ Branch 2 taken 44190 times.
✓ Branch 3 taken 14260 times.
✗ Branch 4 not taken.
|
58450 | true := classTypeEqualIfRecord(st1, st2) or not requireRecordNamesEqual "We need to add a cast from one record to another"; |
| 1477 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 44190 times.
|
44190 | true := listLength(els1) == listLength(els2); |
| 1478 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 44190 times.
|
44190 | true := subtypeVarlist(els1, els2); |
| 1479 | then | ||
| 1480 | true; | ||
| 1481 | |||
| 1482 | // A complex type that extends a basic type is checked against the baseclass basic type | ||
| 1483 | case (DAE.T_SUBTYPE_BASIC(complexType = tp1),tp2) | ||
| 1484 | algorithm | ||
| 1485 | 16336 | res := subtype(tp1, tp2, requireRecordNamesEqual); | |
| 1486 | then | ||
| 1487 | res; | ||
| 1488 | |||
| 1489 | // A complex type that extends a basic type is checked against the baseclass basic type | ||
| 1490 | case (tp1,DAE.T_SUBTYPE_BASIC(complexType = tp2)) | ||
| 1491 | algorithm | ||
| 1492 | 14237 | res := subtype(tp1, tp2, requireRecordNamesEqual); | |
| 1493 | then | ||
| 1494 | res; | ||
| 1495 | |||
| 1496 | // Check of tuples, similar to complex. Just that identifier name do not have to be checked. Only types are checked. | ||
| 1497 | case (DAE.T_TUPLE(types = type_list1), | ||
| 1498 | DAE.T_TUPLE(types = type_list2)) | ||
| 1499 | algorithm | ||
| 1500 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 804 times.
|
804 | true := subtypeTypelist(type_list1, type_list2, requireRecordNamesEqual); |
| 1501 | then | ||
| 1502 | true; | ||
| 1503 | |||
| 1504 | // Part of MetaModelica extension. KS | ||
| 1505 | 24553 | case (DAE.T_METALIST(ty = t1),DAE.T_METALIST(ty = t2)) then subtype(t1,t2); | |
| 1506 | 199 | case (DAE.T_METAARRAY(ty = t1),DAE.T_METAARRAY(ty = t2)) then subtype(t1,t2); | |
| 1507 | case (DAE.T_METATUPLE(types = tList1),DAE.T_METATUPLE(types = tList2)) | ||
| 1508 | algorithm | ||
| 1509 | 24102 | res := subtypeTypelist(tList1,tList2,requireRecordNamesEqual); | |
| 1510 | then res; | ||
| 1511 | case (DAE.T_METAOPTION(ty = t1),DAE.T_METAOPTION(ty = t2)) | ||
| 1512 | 15873 | then subtype(t1,t2,requireRecordNamesEqual); | |
| 1513 | |||
| 1514 | case (DAE.T_METABOXED(ty = t1),DAE.T_METABOXED(ty = t2)) | ||
| 1515 | 9029 | then subtype(t1,t2,requireRecordNamesEqual); | |
| 1516 |
2/2✓ Branch 1 taken 38086 times.
✓ Branch 2 taken 6591 times.
|
44677 | case (DAE.T_METABOXED(ty = t1),t2) algorithm true := isBoxedType(t2); then subtype(t1,t2,requireRecordNamesEqual); |
| 1517 |
2/2✓ Branch 1 taken 73654 times.
✓ Branch 2 taken 15 times.
|
73669 | case (t1,DAE.T_METABOXED(ty = t2)) algorithm true := isBoxedType(t1); then subtype(t1,t2,requireRecordNamesEqual); |
| 1518 | |||
| 1519 |
4/4✓ Branch 0 taken 3305 times.
✓ Branch 1 taken 64 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 3301 times.
|
3369 | case (DAE.T_METAPOLYMORPHIC(name = l1),DAE.T_METAPOLYMORPHIC(name = l2)) then l1 == l2; |
| 1520 | case (DAE.T_UNKNOWN(),_) then true; | ||
| 1521 | case (_,DAE.T_UNKNOWN()) then true; | ||
| 1522 | case (DAE.T_NORETCALL(),DAE.T_NORETCALL()) then true; | ||
| 1523 | |||
| 1524 | // MM Function Reference | ||
| 1525 | case (DAE.T_FUNCTION(funcArg = farg1,funcResultType = t1),DAE.T_FUNCTION(funcArg = farg2,funcResultType = t2)) | ||
| 1526 | algorithm | ||
| 1527 |
4/4✓ Branch 0 taken 238 times.
✓ Branch 1 taken 186 times.
✓ Branch 2 taken 238 times.
✓ Branch 3 taken 186 times.
|
424 | tList1 := list(traverseType(funcArgType(t), 1, unboxedTypeTraverseHelper) for t in farg1); |
| 1528 |
4/4✓ Branch 0 taken 238 times.
✓ Branch 1 taken 186 times.
✓ Branch 2 taken 238 times.
✓ Branch 3 taken 186 times.
|
424 | tList2 := list(traverseType(funcArgType(t), 1, unboxedTypeTraverseHelper) for t in farg2); |
| 1529 | 186 | t1 := traverseType(t1, 1, unboxedTypeTraverseHelper); | |
| 1530 | 186 | t2 := traverseType(t2, 1, unboxedTypeTraverseHelper); | |
| 1531 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 184 times.
|
186 | true := subtypeTypelist(tList1,tList2,requireRecordNamesEqual); |
| 1532 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 184 times.
|
184 | true := subtype(t1,t2,requireRecordNamesEqual); |
| 1533 | then true; | ||
| 1534 | |||
| 1535 | case (DAE.T_FUNCTION_REFERENCE_VAR(functionType = t1),DAE.T_FUNCTION_REFERENCE_VAR(functionType = t2)) | ||
| 1536 | ✗ | then subtype(t1,t2); | |
| 1537 | |||
| 1538 | case (DAE.T_METARECORD(path=p1),DAE.T_METARECORD(path=p2)) | ||
| 1539 | 42953 | then AbsynUtil.pathEqual(p1,p2); | |
| 1540 | |||
| 1541 | case (DAE.T_METAUNIONTYPE(path = p1),DAE.T_METARECORD(utPath=p2)) | ||
| 1542 |
1/2✓ Branch 1 taken 35152 times.
✗ Branch 2 not taken.
|
35152 | then if AbsynUtil.pathEqual(p1,p2) then subtypeTypelist(inType1.typeVars,inType2.typeVars,requireRecordNamesEqual) else false; |
| 1543 | |||
| 1544 | // If the record is the only one in the uniontype, of course their types match | ||
| 1545 | case (DAE.T_METARECORD(knownSingleton=b1,utPath = p1),DAE.T_METAUNIONTYPE(knownSingleton=b2,path=p2)) | ||
| 1546 |
3/4✓ Branch 1 taken 6556 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5284 times.
✓ Branch 4 taken 1272 times.
|
6556 | then if AbsynUtil.pathEqual(p1,p2) and (b1 or b2) /*Values.mo loses knownSingleton information */ then subtypeTypelist(inType1.typeVars,inType2.typeVars,requireRecordNamesEqual) else false; |
| 1547 | |||
| 1548 | // <uniontype> = <uniontype> | ||
| 1549 | case (DAE.T_METAUNIONTYPE(path = p1), DAE.T_METAUNIONTYPE(path = p2)) | ||
| 1550 |
1/2✓ Branch 1 taken 60250 times.
✗ Branch 2 not taken.
|
60250 | then if AbsynUtil.pathEqual(p1,p2) then subtypeTypelist(inType1.typeVars,inType2.typeVars,requireRecordNamesEqual) else false; |
| 1551 | /*case (DAE.T_METAUNIONTYPE(path = p1), DAE.T_COMPLEX(complexClassType=ClassInf.META_UNIONTYPE(_), source = {p2})) | ||
| 1552 | then AbsynUtil.pathEqual(p1,p2); // TODO: Remove? | ||
| 1553 | case(DAE.T_COMPLEX(complexClassType=ClassInf.META_UNIONTYPE(_), source = {p2}), DAE.T_METAUNIONTYPE(path = p1)) | ||
| 1554 | then AbsynUtil.pathEqual(p1,p2); // TODO: Remove?*/ | ||
| 1555 | |||
| 1556 | 2488 | case (DAE.T_CODE(ty = c1),DAE.T_CODE(ty = c2)) then valueEq(c1,c2); | |
| 1557 | |||
| 1558 | ✗ | case (DAE.T_METATYPE(ty = t1),DAE.T_METATYPE(ty = t2)) then subtype(t1,t2,requireRecordNamesEqual); | |
| 1559 | ✗ | case (t1,DAE.T_METATYPE(ty = t2)) then subtype(t1,t2,requireRecordNamesEqual); | |
| 1560 | ✗ | case (DAE.T_METATYPE(ty = t1),t2) then subtype(t1,t2,requireRecordNamesEqual); | |
| 1561 | |||
| 1562 | else | ||
| 1563 | algorithm | ||
| 1564 | /* Uncomment for debugging | ||
| 1565 | l1 = TypesDump.unparseType(t1); | ||
| 1566 | l2 = TypesDump.unparseType(t2); | ||
| 1567 | l1 = stringAppendList({"- Types.subtype failed:\n t1=",l1,"\n t2=",l2}); | ||
| 1568 | print(l1); | ||
| 1569 | */ | ||
| 1570 | then false; | ||
| 1571 | end matchcontinue; | ||
| 1572 | end subtype; | ||
| 1573 | |||
| 1574 | protected function subtypeTypelist "PR. function: subtypeTypelist | ||
| 1575 | This function checks if the both Type lists matches types, element by element." | ||
| 1576 | input list<DAE.Type> inTypeLst1; | ||
| 1577 | input list<DAE.Type> inTypeLst2; | ||
| 1578 | input Boolean requireRecordNamesEqual; | ||
| 1579 | output Boolean outBoolean; | ||
| 1580 | algorithm | ||
| 1581 | outBoolean := match (inTypeLst1, inTypeLst2) | ||
| 1582 | local | ||
| 1583 | Type t1,t2; | ||
| 1584 | list<DAE.Type> rest1,rest2; | ||
| 1585 | |||
| 1586 | case ({}, {}) then true; | ||
| 1587 | case ((t1 :: rest1), (t2 :: rest2)) guard subtype(t1, t2, requireRecordNamesEqual) | ||
| 1588 | 50658 | then subtypeTypelist(rest1, rest2, requireRecordNamesEqual); | |
| 1589 | else false; /* default */ | ||
| 1590 | end match; | ||
| 1591 | end subtypeTypelist; | ||
| 1592 | |||
| 1593 | protected function subtypeVarlist "This function checks if the Var list in the first list is a | ||
| 1594 | subset of the list in the second argument. More precisely, it | ||
| 1595 | checks if, for each Var in the second list there is a Var in | ||
| 1596 | the first list with a type that is a subtype of the Var in the | ||
| 1597 | second list." | ||
| 1598 | input list<DAE.Var> inVarLst1; | ||
| 1599 | input list<DAE.Var> inVarLst2; | ||
| 1600 | output Boolean outBoolean; | ||
| 1601 | algorithm | ||
| 1602 | outBoolean := matchcontinue (inVarLst1,inVarLst2) | ||
| 1603 | local | ||
| 1604 | DAE.Type t1,t2; | ||
| 1605 | list<DAE.Var> l,vs; | ||
| 1606 | String n; | ||
| 1607 | |||
| 1608 | case (_,{}) then true; | ||
| 1609 | |||
| 1610 | case (l,(DAE.TYPES_VAR(name = n,ty = t2) :: vs)) | ||
| 1611 | algorithm | ||
| 1612 | 240792 | DAE.TYPES_VAR(ty = t1) := varlistLookup(l, n); | |
| 1613 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 240792 times.
|
240792 | true := subtype(t1, t2, false); |
| 1614 | 240792 | then subtypeVarlist(l, vs); | |
| 1615 | |||
| 1616 | else false; /* default */ | ||
| 1617 | end matchcontinue; | ||
| 1618 | end subtypeVarlist; | ||
| 1619 | |||
| 1620 | public function varlistLookup "Given a list of Var and a name, this function finds any Var with the given name." | ||
| 1621 | input list<DAE.Var> inVarLst; | ||
| 1622 | input String inIdent; | ||
| 1623 | output DAE.Var outVar; | ||
| 1624 | protected | ||
| 1625 | String name; | ||
| 1626 | algorithm | ||
| 1627 |
1/2✓ Branch 0 taken 1941920 times.
✗ Branch 1 not taken.
|
1941920 | for var in inVarLst loop |
| 1628 | 1941920 | DAE.TYPES_VAR(name = name) := var; | |
| 1629 | |||
| 1630 |
4/4✓ Branch 0 taken 433321 times.
✓ Branch 1 taken 1508599 times.
✓ Branch 3 taken 240792 times.
✓ Branch 4 taken 192529 times.
|
1941920 | if name == inIdent then |
| 1631 | outVar := var; | ||
| 1632 | 240792 | return; | |
| 1633 | end if; | ||
| 1634 | end for; | ||
| 1635 | |||
| 1636 | ✗ | fail(); | |
| 1637 | end varlistLookup; | ||
| 1638 | |||
| 1639 | public function lookupComponent "This function finds a subcomponent by name." | ||
| 1640 | input DAE.Type inType; | ||
| 1641 | input String inIdent; | ||
| 1642 | output DAE.Var outVar; | ||
| 1643 | algorithm | ||
| 1644 | outVar := matchcontinue (inType,inIdent) | ||
| 1645 | local | ||
| 1646 | DAE.Var v; | ||
| 1647 | DAE.Type t,ty; | ||
| 1648 | String n,id; | ||
| 1649 | list<DAE.Var> cs; | ||
| 1650 | DAE.Dimension dim; | ||
| 1651 | |||
| 1652 | case (t,n) | ||
| 1653 | algorithm | ||
| 1654 | ✗ | true := basicType(t); | |
| 1655 | ✗ | v := lookupInBuiltin(t, n); | |
| 1656 | then | ||
| 1657 | v; | ||
| 1658 | |||
| 1659 | case (DAE.T_COMPLEX(varLst = cs),id) | ||
| 1660 | algorithm | ||
| 1661 | ✗ | v := lookupComponent2(cs, id); | |
| 1662 | then | ||
| 1663 | v; | ||
| 1664 | |||
| 1665 | case (DAE.T_SUBTYPE_BASIC(varLst = cs),id) | ||
| 1666 | algorithm | ||
| 1667 | ✗ | v := lookupComponent2(cs, id); | |
| 1668 | then | ||
| 1669 | v; | ||
| 1670 | |||
| 1671 | case (DAE.T_ARRAY(dims = {dim},ty = DAE.T_COMPLEX(varLst = cs)),id) | ||
| 1672 | algorithm | ||
| 1673 | ✗ | v := lookupComponent2(cs, id); | |
| 1674 | ✗ | v.ty := DAE.T_ARRAY(v.ty,{dim}); | |
| 1675 | then | ||
| 1676 | v; | ||
| 1677 | |||
| 1678 | case (DAE.T_ARRAY(dims = {dim},ty = DAE.T_SUBTYPE_BASIC(varLst = cs)),id) | ||
| 1679 | algorithm | ||
| 1680 | ✗ | v := lookupComponent2(cs, id); | |
| 1681 | ✗ | v.ty := DAE.T_ARRAY(v.ty,{dim}); | |
| 1682 | then | ||
| 1683 | v; | ||
| 1684 | |||
| 1685 | else | ||
| 1686 | algorithm | ||
| 1687 | // Print.printBuf("- Looking up " + id + " in noncomplex type\n"); | ||
| 1688 | then fail(); | ||
| 1689 | end matchcontinue; | ||
| 1690 | end lookupComponent; | ||
| 1691 | |||
| 1692 | protected function lookupInBuiltin "Since builtin types are not represented as DAE.T_COMPLEX, special care | ||
| 1693 | is needed to be able to lookup the attributes (*start* etc) in | ||
| 1694 | them. | ||
| 1695 | |||
| 1696 | This is not a complete solution. The current way of mapping the | ||
| 1697 | both the Modelica type Real and the simple type RealType to | ||
| 1698 | DAE.T_REAL is a bit problematic, since it does not make a | ||
| 1699 | difference between Real and RealType, which makes the | ||
| 1700 | translator accept things like x.start.start.start." | ||
| 1701 | input DAE.Type inType; | ||
| 1702 | input String inIdent; | ||
| 1703 | output DAE.Var outVar; | ||
| 1704 | algorithm | ||
| 1705 | outVar := match (inType,inIdent) | ||
| 1706 | local | ||
| 1707 | DAE.Var v; | ||
| 1708 | list<DAE.Var> cs; | ||
| 1709 | String id; | ||
| 1710 | |||
| 1711 | case (DAE.T_REAL(varLst = cs),id) /* Real */ | ||
| 1712 | algorithm | ||
| 1713 | ✗ | v := lookupComponent2(cs, id); | |
| 1714 | then | ||
| 1715 | v; | ||
| 1716 | |||
| 1717 | case (DAE.T_INTEGER(varLst = cs),id) | ||
| 1718 | algorithm | ||
| 1719 | ✗ | v := lookupComponent2(cs, id); | |
| 1720 | then | ||
| 1721 | v; | ||
| 1722 | |||
| 1723 | case (DAE.T_STRING(varLst = cs),id) | ||
| 1724 | algorithm | ||
| 1725 | ✗ | v := lookupComponent2(cs, id); | |
| 1726 | then | ||
| 1727 | v; | ||
| 1728 | |||
| 1729 | case (DAE.T_BOOL(varLst = cs),id) | ||
| 1730 | algorithm | ||
| 1731 | ✗ | v := lookupComponent2(cs, id); | |
| 1732 | then | ||
| 1733 | v; | ||
| 1734 | |||
| 1735 | case (DAE.T_ENUMERATION(index = SOME(_)),"quantity") | ||
| 1736 | then DAE.TYPES_VAR("quantity", DAE.dummyAttrParam,DAE.T_STRING_DEFAULT,DAE.VALBOUND(Values.STRING(""),DAE.BINDING_FROM_DEFAULT_VALUE()),false,NONE()); | ||
| 1737 | |||
| 1738 | // Should be bound to the first element of DAE.T_ENUMERATION list higher up in the call chain | ||
| 1739 | case (DAE.T_ENUMERATION(index = SOME(_)),"min") | ||
| 1740 | then DAE.TYPES_VAR("min", DAE.dummyAttrParam,DAE.T_ENUMERATION(SOME(1),Absyn.IDENT(""),{"min,max"},{},{}),DAE.UNBOUND(),false,NONE()); | ||
| 1741 | |||
| 1742 | // Should be bound to the last element of DAE.T_ENUMERATION list higher up in the call chain | ||
| 1743 | case (DAE.T_ENUMERATION(index = SOME(_)),"max") | ||
| 1744 | then DAE.TYPES_VAR("max", DAE.dummyAttrParam,DAE.T_ENUMERATION(SOME(2),Absyn.IDENT(""),{"min,max"},{},{}),DAE.UNBOUND(),false,NONE()); | ||
| 1745 | |||
| 1746 | // Should be bound to the last element of DAE.T_ENUMERATION list higher up in the call chain | ||
| 1747 | case (DAE.T_ENUMERATION(index = SOME(_)),"start") | ||
| 1748 | then DAE.TYPES_VAR("start", DAE.dummyAttrParam,DAE.T_BOOL_DEFAULT,DAE.UNBOUND(),false,NONE()); | ||
| 1749 | |||
| 1750 | // Needs to be set to true/false higher up the call chain depending on variability of instance | ||
| 1751 | case (DAE.T_ENUMERATION(index = SOME(_)),"fixed") | ||
| 1752 | then DAE.TYPES_VAR("fixed", DAE.dummyAttrParam,DAE.T_BOOL_DEFAULT,DAE.UNBOUND(),false,NONE()); | ||
| 1753 | case (DAE.T_ENUMERATION(index = SOME(_)),"enable") then DAE.TYPES_VAR("enable", DAE.dummyAttrParam,DAE.T_BOOL_DEFAULT,DAE.VALBOUND(Values.BOOL(true),DAE.BINDING_FROM_DEFAULT_VALUE()),false,NONE()); | ||
| 1754 | end match; | ||
| 1755 | end lookupInBuiltin; | ||
| 1756 | |||
| 1757 | protected function lookupComponent2 "This function finds a named Var in a list of Vars, comparing | ||
| 1758 | the name against the second argument to this function." | ||
| 1759 | input list<DAE.Var> inVarLst; | ||
| 1760 | input String inIdent; | ||
| 1761 | output DAE.Var outVar; | ||
| 1762 | algorithm | ||
| 1763 | outVar := match (inVarLst,inIdent) | ||
| 1764 | local | ||
| 1765 | DAE.Var v; | ||
| 1766 | String n,m; | ||
| 1767 | list<DAE.Var> vs; | ||
| 1768 | |||
| 1769 | case (((v as DAE.TYPES_VAR(name = n)) :: _),m) guard stringEq(n, m) | ||
| 1770 | then | ||
| 1771 | v; | ||
| 1772 | |||
| 1773 | case ((_ :: vs),n) | ||
| 1774 | algorithm | ||
| 1775 | ✗ | v := lookupComponent2(vs, n); | |
| 1776 | then | ||
| 1777 | v; | ||
| 1778 | end match; | ||
| 1779 | end lookupComponent2; | ||
| 1780 | |||
| 1781 | public function makeArray "This function makes an array type given a Type and an Absyn.ArrayDim" | ||
| 1782 | input DAE.Type inType; | ||
| 1783 | input Absyn.ArrayDim inArrayDim; | ||
| 1784 | output DAE.Type outType; | ||
| 1785 | algorithm | ||
| 1786 | outType := match (inType,inArrayDim) | ||
| 1787 | local | ||
| 1788 | Type t; | ||
| 1789 | Integer len; | ||
| 1790 | list<Absyn.Subscript> l; | ||
| 1791 | case (t,{}) then t; | ||
| 1792 | case (t,l) | ||
| 1793 | algorithm | ||
| 1794 | ✗ | len := listLength(l); | |
| 1795 | ✗ | then | |
| 1796 | DAE.T_ARRAY(t,{DAE.DIM_INTEGER(len)}); | ||
| 1797 | end match; | ||
| 1798 | end makeArray; | ||
| 1799 | |||
| 1800 | public function makeArraySubscripts " This function makes an array type given a Type and a list of DAE.Subscript" | ||
| 1801 | input DAE.Type inType; | ||
| 1802 | input list<DAE.Subscript> lst; | ||
| 1803 | output DAE.Type outType; | ||
| 1804 | algorithm | ||
| 1805 | outType := matchcontinue (inType,lst) | ||
| 1806 | local | ||
| 1807 | Type t; | ||
| 1808 | Integer i; | ||
| 1809 | list<DAE.Subscript> rest; | ||
| 1810 | case (t,{}) then t; | ||
| 1811 | case (t,DAE.WHOLEDIM()::rest) | ||
| 1812 | algorithm | ||
| 1813 | ✗ | t := makeArraySubscripts(DAE.T_ARRAY(t,{DAE.DIM_UNKNOWN()}),rest); | |
| 1814 | then | ||
| 1815 | t; | ||
| 1816 | case (t,DAE.SLICE(_)::rest) | ||
| 1817 | algorithm | ||
| 1818 | ✗ | t := makeArraySubscripts(DAE.T_ARRAY(t,{DAE.DIM_UNKNOWN()}),rest); | |
| 1819 | then | ||
| 1820 | t; | ||
| 1821 | case (t,DAE.WHOLE_NONEXP(_)::rest) | ||
| 1822 | algorithm | ||
| 1823 | ✗ | t := makeArraySubscripts(DAE.T_ARRAY(t,{DAE.DIM_UNKNOWN()}),rest); | |
| 1824 | then | ||
| 1825 | t; | ||
| 1826 | |||
| 1827 | case (t,DAE.INDEX(DAE.ICONST(i))::rest) | ||
| 1828 | algorithm | ||
| 1829 | ✗ | t := makeArraySubscripts(DAE.T_ARRAY(t,{DAE.DIM_INTEGER(i)}),rest); | |
| 1830 | then | ||
| 1831 | t; | ||
| 1832 | case (t,DAE.INDEX(_)::rest) | ||
| 1833 | algorithm | ||
| 1834 | ✗ | t := makeArraySubscripts(DAE.T_ARRAY(t,{DAE.DIM_UNKNOWN()}),rest); | |
| 1835 | then | ||
| 1836 | t; | ||
| 1837 | end matchcontinue; | ||
| 1838 | end makeArraySubscripts; | ||
| 1839 | |||
| 1840 | public function liftArray "This function turns a type into an array of that type. | ||
| 1841 | If the type already is an array, another dimension is simply added." | ||
| 1842 | input DAE.Type inType; | ||
| 1843 | input DAE.Dimension inDimension; | ||
| 1844 | output DAE.Type outType; | ||
| 1845 | algorithm | ||
| 1846 | 79662 | outType := DAE.T_ARRAY(inType, {inDimension}); | |
| 1847 | end liftArray; | ||
| 1848 | |||
| 1849 | public function liftList "This function turns a type into a list of that type. | ||
| 1850 | If the type already is a list, another dimension is simply added." | ||
| 1851 | input DAE.Type inType; | ||
| 1852 | input DAE.Dimension inDimension; | ||
| 1853 | output DAE.Type outType; | ||
| 1854 | algorithm | ||
| 1855 | 119 | outType := DAE.T_METALIST(inType); | |
| 1856 | end liftList; | ||
| 1857 | |||
| 1858 | public function liftArrayListDims " | ||
| 1859 | This function turns a type into an array of that type." | ||
| 1860 | input DAE.Type inType; | ||
| 1861 | input DAE.Dimensions inDimensions; | ||
| 1862 | output DAE.Type outType = inType; | ||
| 1863 | algorithm | ||
| 1864 |
2/2✓ Branch 2 taken 18142 times.
✓ Branch 3 taken 37393 times.
|
55535 | for dim in listReverse(inDimensions) loop |
| 1865 | 18142 | outType := DAE.T_ARRAY(outType, {dim}); | |
| 1866 | end for; | ||
| 1867 | end liftArrayListDims; | ||
| 1868 | |||
| 1869 | public function liftArrayListDimsReverse | ||
| 1870 | "Turns a type into an array of that type, with the dimensions in the reverse order." | ||
| 1871 | input DAE.Type inType; | ||
| 1872 | input DAE.Dimensions dims; | ||
| 1873 | output DAE.Type ty = inType; | ||
| 1874 | algorithm | ||
| 1875 |
2/2✓ Branch 1 taken 2916 times.
✓ Branch 2 taken 6624 times.
|
9540 | for dim in dims loop |
| 1876 | 2916 | ty := DAE.T_ARRAY(ty, {dim}); | |
| 1877 | end for; | ||
| 1878 | end liftArrayListDimsReverse; | ||
| 1879 | |||
| 1880 | public function liftTypeWithDims " | ||
| 1881 | mahge: This function turns a type into an array of that type | ||
| 1882 | by appening the new dimension at the end. " | ||
| 1883 | input DAE.Type inType; | ||
| 1884 | input DAE.Dimensions inDims; | ||
| 1885 | output DAE.Type outType; | ||
| 1886 | algorithm | ||
| 1887 |
2/2✓ Branch 0 taken 16746 times.
✓ Branch 1 taken 849 times.
|
17595 | if listEmpty(inDims) then |
| 1888 | outType := inType; | ||
| 1889 | 16746 | return; | |
| 1890 | end if; | ||
| 1891 | |||
| 1892 | outType := match inType | ||
| 1893 | local | ||
| 1894 | list<DAE.Dimension> dims; | ||
| 1895 | DAE.Type ty; | ||
| 1896 | |||
| 1897 | case DAE.T_ARRAY(ty=DAE.T_ARRAY()) | ||
| 1898 | algorithm | ||
| 1899 | ✗ | print("Can not handle this yet!!"); | |
| 1900 | ✗ | then fail(); | |
| 1901 | |||
| 1902 | 7 | case DAE.T_ARRAY(ty, dims) then DAE.T_ARRAY(ty, listAppend(dims, inDims)); | |
| 1903 | |||
| 1904 | 842 | else DAE.T_ARRAY(inType, inDims); | |
| 1905 | |||
| 1906 | end match; | ||
| 1907 | end liftTypeWithDims; | ||
| 1908 | |||
| 1909 | public function liftTypeWithDimExps " | ||
| 1910 | This function turns a type into an array of that type." | ||
| 1911 | input DAE.Type inType; | ||
| 1912 | input list<DAE.Exp> inDimExps; | ||
| 1913 | output DAE.Type outType; | ||
| 1914 | algorithm | ||
| 1915 | // outType := liftTypeWithDims(inType, list(DAE.DIM_EXP(e) for e in inDimExps)); | ||
| 1916 | |||
| 1917 | outType := match (inType,inDimExps) | ||
| 1918 | local | ||
| 1919 | Type ty; | ||
| 1920 | DAE.Exp d; | ||
| 1921 | list<DAE.Exp> rest; | ||
| 1922 | case (ty,{}) then ty; | ||
| 1923 | 24 | case (ty,d::rest) then liftArray(liftTypeWithDimExps(ty,rest),DAE.DIM_EXP(d)); | |
| 1924 | end match; | ||
| 1925 | end liftTypeWithDimExps; | ||
| 1926 | |||
| 1927 | public function liftArrayRight "This function adds an array dimension to *the right* of the passed type." | ||
| 1928 | input DAE.Type inType; | ||
| 1929 | input DAE.Dimension inIntegerOption; | ||
| 1930 | output DAE.Type outType; | ||
| 1931 | algorithm | ||
| 1932 | outType := match (inType,inIntegerOption) | ||
| 1933 | local | ||
| 1934 | Type ty_1,ty; | ||
| 1935 | DAE.Dimension dim; | ||
| 1936 | DAE.Dimension d; | ||
| 1937 | ClassInf.State ci; | ||
| 1938 | list<DAE.Var> varlst; | ||
| 1939 | EqualityConstraint ec; | ||
| 1940 | Type tty; | ||
| 1941 | |||
| 1942 | case (DAE.T_ARRAY(dims = {dim},ty = ty),d) | ||
| 1943 | algorithm | ||
| 1944 | 1 | ty_1 := liftArrayRight(ty, d); | |
| 1945 | 1 | then | |
| 1946 | DAE.T_ARRAY(ty_1, {dim}); | ||
| 1947 | |||
| 1948 | case(DAE.T_SUBTYPE_BASIC(ci,varlst,ty,ec),d) guard not listEmpty(TypesDump.getDimensions(ty)) | ||
| 1949 | algorithm | ||
| 1950 | ✗ | ty_1 := liftArrayRight(ty,d); | |
| 1951 | ✗ | then DAE.T_SUBTYPE_BASIC(ci,varlst,ty_1,ec); | |
| 1952 | |||
| 1953 | case (tty,d) | ||
| 1954 | 5 | then | |
| 1955 | DAE.T_ARRAY(tty,{d}); | ||
| 1956 | end match; | ||
| 1957 | end liftArrayRight; | ||
| 1958 | |||
| 1959 | public function unliftArray "This function turns an array of a type into that type." | ||
| 1960 | input DAE.Type inType; | ||
| 1961 | output DAE.Type outType; | ||
| 1962 | algorithm | ||
| 1963 | outType := match inType | ||
| 1964 | local Type ty; | ||
| 1965 | case DAE.T_ARRAY(ty = ty) then ty; | ||
| 1966 | ✗ | case DAE.T_SUBTYPE_BASIC(complexType = ty) then unliftArray(ty); | |
| 1967 | // adrpo: handle also functions returning arrays! | ||
| 1968 | ✗ | case DAE.T_FUNCTION(funcResultType= ty) then unliftArray(ty); | |
| 1969 | end match; | ||
| 1970 | end unliftArray; | ||
| 1971 | |||
| 1972 | public function unliftArrayOrList | ||
| 1973 | input DAE.Type inType; | ||
| 1974 | output DAE.Type outType; | ||
| 1975 | output DAE.Dimension dim; | ||
| 1976 | algorithm | ||
| 1977 | (outType,dim) := match inType | ||
| 1978 | local | ||
| 1979 | Type ty; | ||
| 1980 | 140 | case DAE.T_METALIST(ty = ty) then (boxIfUnboxedType(ty),DAE.DIM_UNKNOWN()); | |
| 1981 | 1 | case DAE.T_METAARRAY(ty = ty) then (boxIfUnboxedType(ty),DAE.DIM_UNKNOWN()); | |
| 1982 | case DAE.T_ARRAY(dims = {dim},ty = ty) then (ty,dim); | ||
| 1983 | case DAE.T_SUBTYPE_BASIC(complexType = ty) | ||
| 1984 | algorithm | ||
| 1985 | ✗ | (ty,dim) := unliftArrayOrList(ty); | |
| 1986 | then (ty,dim); | ||
| 1987 | case DAE.T_FUNCTION(funcResultType = ty) | ||
| 1988 | ✗ | then unliftArrayOrList(ty); | |
| 1989 | end match; | ||
| 1990 | end unliftArrayOrList; | ||
| 1991 | |||
| 1992 | public function arrayElementType "This function turns an array into the element type of the array." | ||
| 1993 | input DAE.Type inType; | ||
| 1994 | output DAE.Type outType; | ||
| 1995 | algorithm | ||
| 1996 | outType := match inType | ||
| 1997 | 3575914 | case DAE.T_ARRAY() then arrayElementType(inType.ty); | |
| 1998 | |||
| 1999 | case DAE.T_SUBTYPE_BASIC() | ||
| 2000 |
2/2✓ Branch 1 taken 10864 times.
✓ Branch 2 taken 172 times.
|
11036 | then if listEmpty(TypesDump.getDimensions(inType.complexType)) then |
| 2001 | inType else arrayElementType(inType.complexType); | ||
| 2002 | |||
| 2003 | 818 | case DAE.T_FUNCTION() then arrayElementType(inType.funcResultType); | |
| 2004 | |||
| 2005 | else inType; | ||
| 2006 | end match; | ||
| 2007 | end arrayElementType; | ||
| 2008 | |||
| 2009 | public function setArrayElementType | ||
| 2010 | input DAE.Type inType; | ||
| 2011 | input DAE.Type inBaseType; | ||
| 2012 | output DAE.Type outType; | ||
| 2013 | algorithm | ||
| 2014 | outType := match inType | ||
| 2015 | local | ||
| 2016 | DAE.Type ty; | ||
| 2017 | DAE.Dimensions dims; | ||
| 2018 | |||
| 2019 | case DAE.T_ARRAY(ty, dims) | ||
| 2020 | algorithm | ||
| 2021 | 101 | ty := setArrayElementType(ty, inBaseType); | |
| 2022 | 101 | then | |
| 2023 | DAE.T_ARRAY(ty, dims); | ||
| 2024 | |||
| 2025 | else inBaseType; | ||
| 2026 | |||
| 2027 | end match; | ||
| 2028 | end setArrayElementType; | ||
| 2029 | |||
| 2030 | public function makeFunctionType "author: LS | ||
| 2031 | Creates a function type from a function name an a list of input and | ||
| 2032 | output variables." | ||
| 2033 | input Absyn.Path p; | ||
| 2034 | input list<DAE.Var> vl; | ||
| 2035 | input DAE.FunctionAttributes functionAttributes; | ||
| 2036 | output DAE.Type outType; | ||
| 2037 | protected | ||
| 2038 | list<DAE.Var> invl,outvl; | ||
| 2039 | list<DAE.FuncArg> fargs; | ||
| 2040 | Type rettype; | ||
| 2041 | algorithm | ||
| 2042 | 69216 | invl := getInputVars(vl); | |
| 2043 | 69216 | outvl := getOutputVars(vl); | |
| 2044 | 69216 | fargs := makeFargsList(invl); | |
| 2045 | 69216 | rettype := makeReturnType(outvl); | |
| 2046 | 69216 | outType := DAE.T_FUNCTION(fargs,rettype,functionAttributes,p); | |
| 2047 | end makeFunctionType; | ||
| 2048 | |||
| 2049 | public function extendsFunctionTypeArgs | ||
| 2050 | "function: extandFunctionType | ||
| 2051 | Extends function argument list adding var for element list." | ||
| 2052 | input DAE.Type inType; | ||
| 2053 | input list<DAE.Element> inElementLst; | ||
| 2054 | input list<DAE.Element> inOutputElementLst; | ||
| 2055 | input list<Boolean> inBooltLst; | ||
| 2056 | output DAE.Type outType; | ||
| 2057 | protected | ||
| 2058 | Absyn.Path tysrc; | ||
| 2059 | list<DAE.FuncArg> fargs, fargs1, newfargs; | ||
| 2060 | DAE.Type rettype; | ||
| 2061 | DAE.FunctionAttributes functionAttributes; | ||
| 2062 | algorithm | ||
| 2063 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
|
77 | DAE.T_FUNCTION(fargs,rettype,functionAttributes,tysrc) := inType; |
| 2064 | 77 | (fargs1, _) := List.splitOnBoolList(fargs, inBooltLst); | |
| 2065 | 77 | newfargs := List.threadMap(inElementLst, fargs1, makeElementFarg); | |
| 2066 | 77 | newfargs := listAppend(fargs, newfargs); | |
| 2067 | // The type of DAE.Element.VAR seems to be wrong, | ||
| 2068 | // but the original type should be also correct | ||
| 2069 | //rettype := makeElementReturnType(inOutputElementLst); | ||
| 2070 | 77 | outType := DAE.T_FUNCTION(newfargs,rettype,functionAttributes,tysrc); | |
| 2071 | end extendsFunctionTypeArgs; | ||
| 2072 | |||
| 2073 | public function setFunctionNoReturn | ||
| 2074 | "Marks a function type as never returning normally, so that callers can treat | ||
| 2075 | calls to it as terminating." | ||
| 2076 | input output DAE.Type ty; | ||
| 2077 | algorithm | ||
| 2078 | ty := match ty | ||
| 2079 | local | ||
| 2080 | list<DAE.FuncArg> fargs; | ||
| 2081 | DAE.Type rettype; | ||
| 2082 | Absyn.Path p; | ||
| 2083 | DAE.InlineType inl; | ||
| 2084 | Boolean ge, fp; | ||
| 2085 | DAE.Purity pu; | ||
| 2086 | DAE.FunctionBuiltin bi; | ||
| 2087 | DAE.FunctionParallelism par; | ||
| 2088 | case DAE.T_FUNCTION(fargs, rettype, DAE.FUNCTION_ATTRIBUTES(inl,ge,pu,fp,bi,par,_), p) | ||
| 2089 |
2/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
30 | then DAE.T_FUNCTION(fargs, rettype, DAE.FUNCTION_ATTRIBUTES(inl,ge,pu,fp,bi,par,DAE.NoReturn.NORETURN), p); |
| 2090 | else ty; | ||
| 2091 | end match; | ||
| 2092 | end setFunctionNoReturn; | ||
| 2093 | |||
| 2094 | protected function makeElementReturnType " | ||
| 2095 | Create a return type from a list of Element output variables. | ||
| 2096 | Depending on the length of the output variable list, different | ||
| 2097 | kinds of return types are created." | ||
| 2098 | input list<DAE.Element> inElementLst; | ||
| 2099 | output DAE.Type outType; | ||
| 2100 | algorithm | ||
| 2101 | outType := match inElementLst | ||
| 2102 | local | ||
| 2103 | Type ty; | ||
| 2104 | DAE.Element element; | ||
| 2105 | list<DAE.Element> elements; | ||
| 2106 | list<Type> types; | ||
| 2107 | list<String> names; | ||
| 2108 | Option<list<String>> namesOpt; | ||
| 2109 | |||
| 2110 | |||
| 2111 | case {} then DAE.T_NORETCALL(); | ||
| 2112 | |||
| 2113 | case {element} | ||
| 2114 | algorithm | ||
| 2115 | ✗ | ty := makeElementReturnTypeSingle(element); | |
| 2116 | then | ||
| 2117 | ty; | ||
| 2118 | |||
| 2119 | case elements | ||
| 2120 | algorithm | ||
| 2121 | types := {}; | ||
| 2122 | names := {}; | ||
| 2123 | ✗ | for element in elements loop | |
| 2124 | ✗ | types := makeElementReturnTypeSingle(element)::types; | |
| 2125 | ✗ | names := DAEUtil.varName(element)::names; | |
| 2126 | end for; | ||
| 2127 | ✗ | if listEmpty(names) then | |
| 2128 | namesOpt := NONE(); | ||
| 2129 | else | ||
| 2130 | ✗ | namesOpt := SOME(listReverse(names)); | |
| 2131 | end if; | ||
| 2132 | ✗ | then DAE.T_TUPLE(listReverse(types), namesOpt); | |
| 2133 | end match; | ||
| 2134 | end makeElementReturnType; | ||
| 2135 | |||
| 2136 | protected function makeElementReturnTypeSingle | ||
| 2137 | "Create the return type from an Element for a single return value." | ||
| 2138 | input DAE.Element inElement; | ||
| 2139 | output DAE.Type outType; | ||
| 2140 | algorithm | ||
| 2141 | outType := match inElement | ||
| 2142 | local | ||
| 2143 | Type ty; | ||
| 2144 | |||
| 2145 | case DAE.VAR(ty = ty) then ty; | ||
| 2146 | end match; | ||
| 2147 | end makeElementReturnTypeSingle; | ||
| 2148 | |||
| 2149 | public function getNthEnumLiteral | ||
| 2150 | "Returns the n:th literal of an enumeration type." | ||
| 2151 | input DAE.Type ty; | ||
| 2152 | input Integer n; | ||
| 2153 | output DAE.Exp literalExp; | ||
| 2154 | algorithm | ||
| 2155 | literalExp := match ty | ||
| 2156 | case DAE.T_ENUMERATION() | ||
| 2157 | 546 | then DAE.ENUM_LITERAL(AbsynUtil.joinPaths(ty.path, Absyn.IDENT(listGet(ty.names, n))), n); | |
| 2158 | |||
| 2159 | // Not sure if this is correct, maybe it would be more correct to | ||
| 2160 | // use the path in the ClassInf.State inside the subtype? | ||
| 2161 | case DAE.T_SUBTYPE_BASIC() | ||
| 2162 | ✗ | then getNthEnumLiteral(ty.complexType, n); | |
| 2163 | end match; | ||
| 2164 | end getNthEnumLiteral; | ||
| 2165 | |||
| 2166 | public function makeEnumerationType | ||
| 2167 | "Creates an enumeration type from a name and an enumeration type containing | ||
| 2168 | the literal variables." | ||
| 2169 | input Absyn.Path inPath; | ||
| 2170 | input DAE.Type inType; | ||
| 2171 | output DAE.Type outType; | ||
| 2172 | algorithm | ||
| 2173 | outType := matchcontinue inType | ||
| 2174 | local | ||
| 2175 | Absyn.Path p; | ||
| 2176 | list<String> names, attr_names; | ||
| 2177 | list<DAE.Var> vars, attrs; | ||
| 2178 | Type ty; | ||
| 2179 | |||
| 2180 | case DAE.T_ENUMERATION(index = NONE(), path = p, names = names, literalVarLst = vars, attributeLst = attrs) | ||
| 2181 | algorithm | ||
| 2182 | 7599 | vars := makeEnumerationType1(p, vars, names, 1); | |
| 2183 | 7599 | attr_names := List.map(vars, TypesDump.getVarName); | |
| 2184 | 7599 | attrs := makeEnumerationType1(p, attrs, attr_names, 1); | |
| 2185 | 7599 | then (DAE.T_ENUMERATION(NONE(), p, names, vars, attrs)); | |
| 2186 | |||
| 2187 | case DAE.T_ARRAY(ty = ty) | ||
| 2188 | 1706 | then makeEnumerationType(inPath, ty); | |
| 2189 | |||
| 2190 | else | ||
| 2191 | algorithm | ||
| 2192 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 2193 | ✗ | Debug.traceln("- Types.makeEnumerationType failed on " + TypesDump.printTypeStr(inType)); | |
| 2194 | ✗ | then | |
| 2195 | fail(); | ||
| 2196 | end matchcontinue; | ||
| 2197 | end makeEnumerationType; | ||
| 2198 | |||
| 2199 | public function makeEnumerationType1 | ||
| 2200 | "Helper function to makeEnumerationType. Updates a list of enumeration | ||
| 2201 | literals with the correct index and type." | ||
| 2202 | input Absyn.Path inPath; | ||
| 2203 | input list<DAE.Var> inVarLst; | ||
| 2204 | input list<String> inNames; | ||
| 2205 | input Integer inIdx; | ||
| 2206 | output list<DAE.Var> outVarLst; | ||
| 2207 | algorithm | ||
| 2208 | outVarLst := match (inPath,inVarLst,inNames,inIdx) | ||
| 2209 | local | ||
| 2210 | list<String> names; | ||
| 2211 | Absyn.Path p; | ||
| 2212 | String name; | ||
| 2213 | list<DAE.Var> xs,vars; | ||
| 2214 | DAE.Type t; | ||
| 2215 | Integer idx; | ||
| 2216 | DAE.Attributes attributes; | ||
| 2217 | DAE.Binding binding; | ||
| 2218 | Boolean bsrc; | ||
| 2219 | DAE.Var var; | ||
| 2220 | Option<DAE.Const> cnstForRange; | ||
| 2221 | |||
| 2222 | case (p,DAE.TYPES_VAR(name,attributes,_,binding,bsrc,cnstForRange) :: xs,names,idx) | ||
| 2223 | algorithm | ||
| 2224 | 42645 | vars := makeEnumerationType1(p, xs, names, idx+1); | |
| 2225 | 42645 | t := DAE.T_ENUMERATION(SOME(idx),p,names,{},{}); | |
| 2226 |
1/2✓ Branch 0 taken 42645 times.
✗ Branch 1 not taken.
|
85290 | var := DAE.TYPES_VAR(name,attributes,t,binding,bsrc,cnstForRange); |
| 2227 | then | ||
| 2228 | (var :: vars); | ||
| 2229 | case (_,{},_,_) then {}; | ||
| 2230 | end match; | ||
| 2231 | end makeEnumerationType1; | ||
| 2232 | |||
| 2233 | protected function getInputVars "author: LS | ||
| 2234 | Retrieve all the input variables from a list of variables." | ||
| 2235 | input list<DAE.Var> vl; | ||
| 2236 | output list<DAE.Var> vl_1; | ||
| 2237 | algorithm | ||
| 2238 | 69216 | vl_1 := List.select(vl, isInputVar); | |
| 2239 | end getInputVars; | ||
| 2240 | |||
| 2241 | protected function getOutputVars "Retrieve all output variables from a list of variables." | ||
| 2242 | input list<DAE.Var> vl; | ||
| 2243 | output list<DAE.Var> vl_1; | ||
| 2244 | algorithm | ||
| 2245 | 69216 | vl_1 := List.select(vl, isOutputVar); | |
| 2246 | end getOutputVars; | ||
| 2247 | |||
| 2248 | public function getFixedVarAttributeParameterOrConstant | ||
| 2249 | "Returns the value of the fixed attribute of a builtin type. | ||
| 2250 | If there is no fixed in the tyep it returns true" | ||
| 2251 | input DAE.Type tp; | ||
| 2252 | output Boolean fix; | ||
| 2253 | algorithm | ||
| 2254 | try | ||
| 2255 | // there is a fixed! | ||
| 2256 | 1273 | fix := getFixedVarAttribute(tp); | |
| 2257 | else | ||
| 2258 | // there is no fixed! | ||
| 2259 | fix := true; | ||
| 2260 | end try; | ||
| 2261 | end getFixedVarAttributeParameterOrConstant; | ||
| 2262 | |||
| 2263 | public function getFixedVarAttribute "Returns the value of the fixed attribute of a builtin type" | ||
| 2264 | input DAE.Type tp; | ||
| 2265 | output Boolean fixed; | ||
| 2266 | algorithm | ||
| 2267 | fixed := matchcontinue tp | ||
| 2268 | local | ||
| 2269 | Type ty; | ||
| 2270 | Boolean result; | ||
| 2271 | list<DAE.Var> vars; | ||
| 2272 | |||
| 2273 | case DAE.T_REAL(varLst = DAE.TYPES_VAR(name = "fixed",binding = DAE.VALBOUND(valBound = Values.BOOL(fixed)))::_) then fixed; | ||
| 2274 | case DAE.T_REAL(varLst = DAE.TYPES_VAR(name = "fixed",binding = DAE.EQBOUND(evaluatedExp = SOME(Values.BOOL(fixed))))::_) then fixed; | ||
| 2275 | case DAE.T_REAL(varLst = DAE.TYPES_VAR(name = "fixed",binding = DAE.EQBOUND(exp = DAE.BCONST(fixed)))::_) then fixed; | ||
| 2276 | case DAE.T_REAL(varLst = _::vars) algorithm | ||
| 2277 | 575 | fixed := getFixedVarAttribute(DAE.T_REAL(vars)); | |
| 2278 | then fixed; | ||
| 2279 | |||
| 2280 | case DAE.T_INTEGER(varLst = DAE.TYPES_VAR(name = "fixed",binding = DAE.VALBOUND(valBound = Values.BOOL(fixed)))::_) then fixed; | ||
| 2281 | case DAE.T_INTEGER(varLst = DAE.TYPES_VAR(name = "fixed",binding = DAE.EQBOUND(evaluatedExp = SOME(Values.BOOL(fixed))))::_) then fixed; | ||
| 2282 | case DAE.T_INTEGER(varLst = DAE.TYPES_VAR(name = "fixed",binding = DAE.EQBOUND(exp = DAE.BCONST(fixed)))::_) then fixed; | ||
| 2283 | case DAE.T_INTEGER(varLst = _::vars) algorithm | ||
| 2284 | 4 | fixed := getFixedVarAttribute(DAE.T_INTEGER(vars)); | |
| 2285 | then fixed; | ||
| 2286 | |||
| 2287 | case DAE.T_BOOL(varLst = DAE.TYPES_VAR(name = "fixed",binding = DAE.VALBOUND(valBound = Values.BOOL(fixed)))::_) then fixed; | ||
| 2288 | case DAE.T_BOOL(varLst = DAE.TYPES_VAR(name = "fixed",binding = DAE.EQBOUND(evaluatedExp = SOME(Values.BOOL(fixed))))::_) then fixed; | ||
| 2289 | case DAE.T_BOOL(varLst = DAE.TYPES_VAR(name = "fixed",binding = DAE.EQBOUND(exp = DAE.BCONST(fixed)))::_) then fixed; | ||
| 2290 | case DAE.T_BOOL(varLst = _::vars) algorithm | ||
| 2291 | ✗ | fixed := getFixedVarAttribute(DAE.T_BOOL(vars)); | |
| 2292 | then fixed; | ||
| 2293 | |||
| 2294 | case DAE.T_ARRAY(ty = ty) | ||
| 2295 | algorithm | ||
| 2296 | 695 | result := getFixedVarAttribute(ty); | |
| 2297 | then | ||
| 2298 | result; | ||
| 2299 | end matchcontinue; | ||
| 2300 | end getFixedVarAttribute; | ||
| 2301 | |||
| 2302 | public function getConnectorVars | ||
| 2303 | "Returns the list of variables in a connector, or fails if the type is not a | ||
| 2304 | connector." | ||
| 2305 | input DAE.Type inType; | ||
| 2306 | output list<DAE.Var> outVars; | ||
| 2307 | algorithm | ||
| 2308 | outVars := match inType | ||
| 2309 | local list<DAE.Var> vars; | ||
| 2310 | case DAE.T_COMPLEX( | ||
| 2311 | complexClassType = ClassInf.CONNECTOR(), | ||
| 2312 | varLst = vars) | ||
| 2313 | then vars; | ||
| 2314 | end match; | ||
| 2315 | end getConnectorVars; | ||
| 2316 | |||
| 2317 | public function isInputVar | ||
| 2318 | "Succeds if variable is an input variable." | ||
| 2319 | input DAE.Var inVar; | ||
| 2320 | output Boolean b; | ||
| 2321 | algorithm | ||
| 2322 | b := match inVar | ||
| 2323 | local | ||
| 2324 | DAE.Attributes attr; | ||
| 2325 | |||
| 2326 | case DAE.TYPES_VAR(attributes = attr) | ||
| 2327 |
3/4✓ Branch 1 taken 189770 times.
✓ Branch 2 taken 121773 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 189770 times.
|
311543 | then isInputAttr(attr) and isPublicAttr(attr); |
| 2328 | end match; | ||
| 2329 | end isInputVar; | ||
| 2330 | |||
| 2331 | public function isOutputVar | ||
| 2332 | "Succeds if variable is an output variable." | ||
| 2333 | input DAE.Var inVar; | ||
| 2334 | output Boolean b; | ||
| 2335 | algorithm | ||
| 2336 | b := match inVar | ||
| 2337 | local | ||
| 2338 | DAE.Attributes attr; | ||
| 2339 | |||
| 2340 | case DAE.TYPES_VAR(attributes = attr) | ||
| 2341 |
3/4✓ Branch 1 taken 135315 times.
✓ Branch 2 taken 248242 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 135315 times.
|
383557 | then isOutputAttr(attr) and isPublicAttr(attr); |
| 2342 | end match; | ||
| 2343 | end isOutputVar; | ||
| 2344 | |||
| 2345 | public function isInputAttr "Returns true if the Attributes of a variable indicates | ||
| 2346 | that the variable is input." | ||
| 2347 | input DAE.Attributes inAttributes; | ||
| 2348 | output Boolean outBoolean; | ||
| 2349 | algorithm | ||
| 2350 | outBoolean := match inAttributes | ||
| 2351 | case DAE.ATTR(direction = Absyn.INPUT()) then true; | ||
| 2352 | else false; | ||
| 2353 | end match; | ||
| 2354 | end isInputAttr; | ||
| 2355 | |||
| 2356 | public function isOutputAttr "Returns true if the Attributes of a variable indicates | ||
| 2357 | that the variable is output." | ||
| 2358 | input DAE.Attributes inAttributes; | ||
| 2359 | output Boolean outBoolean; | ||
| 2360 | algorithm | ||
| 2361 | outBoolean := match inAttributes | ||
| 2362 | case DAE.ATTR(direction = Absyn.OUTPUT()) then true; | ||
| 2363 | else false; | ||
| 2364 | end match; | ||
| 2365 | end isOutputAttr; | ||
| 2366 | |||
| 2367 | public function isBidirAttr "Returns true if the Attributes of a variable indicates that the variable | ||
| 2368 | is bidirectional, i.e. neither input nor output." | ||
| 2369 | input DAE.Attributes inAttributes; | ||
| 2370 | output Boolean outBoolean; | ||
| 2371 | algorithm | ||
| 2372 | outBoolean := match inAttributes | ||
| 2373 | case DAE.ATTR(direction = Absyn.BIDIR()) then true; | ||
| 2374 | else false; | ||
| 2375 | end match; | ||
| 2376 | end isBidirAttr; | ||
| 2377 | |||
| 2378 | public function isPublicAttr | ||
| 2379 | input DAE.Attributes inAttributes; | ||
| 2380 | output Boolean outIsPublic; | ||
| 2381 | algorithm | ||
| 2382 | outIsPublic := match inAttributes | ||
| 2383 | case DAE.ATTR(visibility = SCode.PUBLIC()) then true; | ||
| 2384 | else false; | ||
| 2385 | end match; | ||
| 2386 | end isPublicAttr; | ||
| 2387 | |||
| 2388 | public function isConstAttr | ||
| 2389 | input DAE.Attributes inAttributes; | ||
| 2390 | output Boolean outIsPublic; | ||
| 2391 | algorithm | ||
| 2392 | outIsPublic := match inAttributes | ||
| 2393 | case DAE.ATTR(variability = SCode.CONST()) then true; | ||
| 2394 | else false; | ||
| 2395 | end match; | ||
| 2396 | end isConstAttr; | ||
| 2397 | |||
| 2398 | public function isPublicVar | ||
| 2399 | input DAE.Var inVar; | ||
| 2400 | output Boolean b; | ||
| 2401 | algorithm | ||
| 2402 | b := match inVar | ||
| 2403 | 78995 | case DAE.TYPES_VAR() then isPublicAttr(inVar.attributes); | |
| 2404 | end match; | ||
| 2405 | end isPublicVar; | ||
| 2406 | |||
| 2407 | public function isConstVar | ||
| 2408 | input DAE.Var inVar; | ||
| 2409 | output Boolean b; | ||
| 2410 | algorithm | ||
| 2411 | b := match inVar | ||
| 2412 | 76835 | case DAE.TYPES_VAR() then isConstAttr(inVar.attributes); | |
| 2413 | end match; | ||
| 2414 | end isConstVar; | ||
| 2415 | |||
| 2416 | // This used in creation of record constructors to decide wether a variable should be | ||
| 2417 | // part of the constructor signature or not. If a var is modifiable from outside then | ||
| 2418 | // it is part of the construvtor signature. | ||
| 2419 | public function isModifiableTypesVar | ||
| 2420 | input DAE.Var inVar; | ||
| 2421 | output Boolean b; | ||
| 2422 | algorithm | ||
| 2423 | |||
| 2424 | // protected vars are not modifiable from outside. | ||
| 2425 |
2/2✓ Branch 1 taken 242 times.
✓ Branch 2 taken 76835 times.
|
77077 | if not isPublicVar(inVar) then |
| 2426 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 242 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 242 times.
|
242 | if isNone(getBindingExpOptional(inVar)) then |
| 2427 | // TYPES_VAR has no info. For now this suffices. | ||
| 2428 | ✗ | Error.addSourceMessage(Error.MISSING_BINDING_PROTECTED_RECORD_VAR, {TypesDump.getVarName(inVar)}, Absyn.dummyInfo); | |
| 2429 | end if; | ||
| 2430 | |||
| 2431 | b := false; | ||
| 2432 | 242 | return; | |
| 2433 | end if; | ||
| 2434 | |||
| 2435 | // const vars which already have binding are not modifiable from outside. | ||
| 2436 |
4/6✓ Branch 1 taken 1324 times.
✓ Branch 2 taken 75511 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1324 times.
✓ Branch 8 taken 1324 times.
✗ Branch 9 not taken.
|
76835 | if isConstVar(inVar) and isSome(getBindingExpOptional(inVar)) then |
| 2437 | b := false; | ||
| 2438 | 1324 | return; | |
| 2439 | end if; | ||
| 2440 | |||
| 2441 | // otherwise modifiable | ||
| 2442 | b := true; | ||
| 2443 | end isModifiableTypesVar; | ||
| 2444 | |||
| 2445 | public function getBindingExpOptional | ||
| 2446 | input DAE.Var inVar; | ||
| 2447 | output Option<DAE.Exp> outExp; | ||
| 2448 | algorithm | ||
| 2449 | outExp := match inVar | ||
| 2450 | local | ||
| 2451 | DAE.Exp exp; | ||
| 2452 | case DAE.TYPES_VAR(binding=DAE.EQBOUND(exp=exp)) then SOME(exp); | ||
| 2453 | else NONE(); | ||
| 2454 | end match; | ||
| 2455 | end getBindingExpOptional; | ||
| 2456 | |||
| 2457 | // This should be removed. It is used in cevalScript now. cevalScript should be updated | ||
| 2458 | // and this removed. | ||
| 2459 | public function getBindingExp | ||
| 2460 | input DAE.Var inVar; | ||
| 2461 | input Absyn.Path inPath; | ||
| 2462 | output DAE.Exp outExp; | ||
| 2463 | algorithm | ||
| 2464 | outExp := match inVar | ||
| 2465 | local | ||
| 2466 | DAE.Exp exp; | ||
| 2467 | String str; | ||
| 2468 | String name; | ||
| 2469 | |||
| 2470 | case DAE.TYPES_VAR(binding=DAE.EQBOUND(exp=exp)) then exp; | ||
| 2471 | case DAE.TYPES_VAR(name=name, binding=DAE.UNBOUND()) | ||
| 2472 | algorithm | ||
| 2473 | ✗ | str := "Record '" + AbsynUtil.pathString(inPath) + "' member '" + name + "' has no default value and is not modifiable by a constructor function.\n"; | |
| 2474 | ✗ | Error.addCompilerWarning(str); | |
| 2475 | then | ||
| 2476 | DAE.ICONST(0); | ||
| 2477 | end match; | ||
| 2478 | end getBindingExp; | ||
| 2479 | |||
| 2480 | public function makeFargsList | ||
| 2481 | "Makes a function argument list from a list of variables." | ||
| 2482 | input list<DAE.Var> vars; | ||
| 2483 | output list<DAE.FuncArg> fargs; | ||
| 2484 | annotation(__OpenModelica_EarlyInline=true); | ||
| 2485 | algorithm | ||
| 2486 | 7028 | fargs := List.map(vars,makeFarg); | |
| 2487 | end makeFargsList; | ||
| 2488 | |||
| 2489 | protected function makeFarg | ||
| 2490 | "Makes a function argument list from a variable." | ||
| 2491 | input DAE.Var variable; | ||
| 2492 | output DAE.FuncArg farg; | ||
| 2493 | algorithm | ||
| 2494 | farg := match variable | ||
| 2495 | local | ||
| 2496 | String n; | ||
| 2497 | DAE.Type ty; | ||
| 2498 | DAE.Binding bnd; | ||
| 2499 | DAE.Const c; | ||
| 2500 | DAE.VarParallelism p; | ||
| 2501 | SCode.Variability var; | ||
| 2502 | SCode.Parallelism par; | ||
| 2503 | Option<DAE.Exp> oexp; | ||
| 2504 | |||
| 2505 | case DAE.TYPES_VAR(name = n,attributes = DAE.ATTR(variability = var, parallelism = par),ty = ty,binding = bnd) | ||
| 2506 | algorithm | ||
| 2507 | 182956 | c := variabilityToConst(var); | |
| 2508 | 182956 | p := DAEUtil.scodePrlToDaePrl(par); | |
| 2509 | 182956 | oexp := DAEUtil.bindingExp(bnd); | |
| 2510 | 182956 | then DAE.FUNCARG(n,ty,c,p,oexp); | |
| 2511 | end match; | ||
| 2512 | end makeFarg; | ||
| 2513 | |||
| 2514 | protected function makeElementFarg | ||
| 2515 | "Makes a function argument list from a variable." | ||
| 2516 | input DAE.Element inElement; | ||
| 2517 | input DAE.FuncArg inFarg; | ||
| 2518 | output DAE.FuncArg farg; | ||
| 2519 | algorithm | ||
| 2520 | farg := match inElement | ||
| 2521 | local | ||
| 2522 | String name; | ||
| 2523 | DAE.ComponentRef cref; | ||
| 2524 | |||
| 2525 | case DAE.VAR(componentRef=cref) | ||
| 2526 | algorithm | ||
| 2527 | 168 | name := ComponentReferenceBasics.crefLastIdent(cref); | |
| 2528 | 168 | then setFuncArgName(inFarg, name); | |
| 2529 | end match; | ||
| 2530 | end makeElementFarg; | ||
| 2531 | |||
| 2532 | protected function makeReturnType "author: LS | ||
| 2533 | Create a return type from a list of output variables. | ||
| 2534 | Depending on the length of the output variable list, different | ||
| 2535 | kinds of return types are created." | ||
| 2536 | input list<DAE.Var> inVarLst; | ||
| 2537 | output DAE.Type outType; | ||
| 2538 | algorithm | ||
| 2539 | outType := match inVarLst | ||
| 2540 | local | ||
| 2541 | Type ty; | ||
| 2542 | Var var; | ||
| 2543 | list<DAE.Var> vl; | ||
| 2544 | |||
| 2545 | case {} then DAE.T_NORETCALL(); | ||
| 2546 | |||
| 2547 | case {var} | ||
| 2548 | algorithm | ||
| 2549 | 63310 | ty := makeReturnTypeSingle(var); | |
| 2550 | then | ||
| 2551 | ty; | ||
| 2552 | |||
| 2553 | case vl | ||
| 2554 |
8/8✓ Branch 0 taken 4675 times.
✓ Branch 1 taken 1867 times.
✓ Branch 2 taken 4675 times.
✓ Branch 3 taken 1867 times.
✓ Branch 5 taken 4675 times.
✓ Branch 6 taken 1867 times.
✓ Branch 7 taken 4675 times.
✓ Branch 8 taken 1867 times.
|
11217 | then DAE.T_TUPLE( |
| 2555 | list(makeReturnTypeSingle(v) for v in vl), | ||
| 2556 | SOME(list(TypesDump.getVarName(v) for v in vl))); | ||
| 2557 | end match; | ||
| 2558 | end makeReturnType; | ||
| 2559 | |||
| 2560 | protected function makeReturnTypeSingle "author: LS | ||
| 2561 | Create the return type for a single return value." | ||
| 2562 | input DAE.Var inVar; | ||
| 2563 | output DAE.Type outType; | ||
| 2564 | algorithm | ||
| 2565 | outType := match inVar | ||
| 2566 | local | ||
| 2567 | Type ty; | ||
| 2568 | |||
| 2569 | case DAE.TYPES_VAR(ty = ty) then ty; | ||
| 2570 | end match; | ||
| 2571 | end makeReturnTypeSingle; | ||
| 2572 | |||
| 2573 | public function isParameterVar "author: LS | ||
| 2574 | Succeds if a variable is a parameter." | ||
| 2575 | input DAE.Var inVar; | ||
| 2576 | algorithm | ||
| 2577 | ✗ | DAE.TYPES_VAR(attributes = DAE.ATTR(variability = SCode.PARAM(),visibility = SCode.PUBLIC())) := inVar; | |
| 2578 | end isParameterVar; | ||
| 2579 | |||
| 2580 | public function isConstant | ||
| 2581 | "Returns true of c is C_CONST." | ||
| 2582 | input DAE.Const c; | ||
| 2583 | output Boolean b; | ||
| 2584 | algorithm | ||
| 2585 | b := match c | ||
| 2586 | case DAE.C_CONST() then true; | ||
| 2587 | else false; | ||
| 2588 | end match; | ||
| 2589 | end isConstant; | ||
| 2590 | |||
| 2591 | public function isParameter | ||
| 2592 | "Returns true if c is C_PARAM." | ||
| 2593 | input DAE.Const c; | ||
| 2594 | output Boolean b; | ||
| 2595 | algorithm | ||
| 2596 | b := match c | ||
| 2597 | case DAE.C_PARAM() then true; | ||
| 2598 | else false; | ||
| 2599 | end match; | ||
| 2600 | end isParameter; | ||
| 2601 | |||
| 2602 | public function isParameterOrConstant "returns true if Const is PARAM or CONST" | ||
| 2603 | input DAE.Const c; | ||
| 2604 | output Boolean b; | ||
| 2605 | algorithm | ||
| 2606 | b := match c | ||
| 2607 | case DAE.C_CONST() then true; | ||
| 2608 | case DAE.C_PARAM() then true; | ||
| 2609 | else false; | ||
| 2610 | end match; | ||
| 2611 | end isParameterOrConstant; | ||
| 2612 | |||
| 2613 | public function isVar | ||
| 2614 | input DAE.Const inConst; | ||
| 2615 | output Boolean outIsVar; | ||
| 2616 | algorithm | ||
| 2617 | outIsVar := match inConst | ||
| 2618 | case DAE.C_VAR() then true; | ||
| 2619 | else false; | ||
| 2620 | end match; | ||
| 2621 | end isVar; | ||
| 2622 | |||
| 2623 | public function propsContainReal | ||
| 2624 | "Returns true if any of the given properties contains a Real type." | ||
| 2625 | input list<DAE.Properties> inProperties; | ||
| 2626 | output Boolean outHasReal = false; | ||
| 2627 | algorithm | ||
| 2628 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | for prop in inProperties loop |
| 2629 |
2/2✓ Branch 2 taken 2 times.
✓ Branch 3 taken 20 times.
|
22 | if isReal(getPropType(prop)) then |
| 2630 | outHasReal := true; | ||
| 2631 | break; | ||
| 2632 | end if; | ||
| 2633 | end for; | ||
| 2634 | end propsContainReal; | ||
| 2635 | |||
| 2636 | public function containReal | ||
| 2637 | "Returns true if a builtin type, or array-type is Real." | ||
| 2638 | input list<DAE.Type> inTypes; | ||
| 2639 | output Boolean outHasReal; | ||
| 2640 | algorithm | ||
| 2641 |
2/2✓ Branch 0 taken 3338 times.
✓ Branch 1 taken 208 times.
|
3546 | for ty in inTypes loop |
| 2642 |
2/2✓ Branch 1 taken 437 times.
✓ Branch 2 taken 2901 times.
|
3338 | if isReal(ty) then |
| 2643 | outHasReal := true; | ||
| 2644 | 437 | return; | |
| 2645 | end if; | ||
| 2646 | end for; | ||
| 2647 | outHasReal := false; | ||
| 2648 | end containReal; | ||
| 2649 | |||
| 2650 | public function propAllConst "author: LS | ||
| 2651 | If PROP_TUPLE, returns true if all of the flags are constant." | ||
| 2652 | input DAE.Properties inProperties; | ||
| 2653 | output DAE.Const outConst; | ||
| 2654 | algorithm | ||
| 2655 | outConst := matchcontinue inProperties | ||
| 2656 | local | ||
| 2657 | DAE.Const c,res; | ||
| 2658 | DAE.TupleConst constant_; | ||
| 2659 | String str; | ||
| 2660 | DAE.Properties prop; | ||
| 2661 | case DAE.PROP(constFlag = c) then c; | ||
| 2662 | case DAE.PROP_TUPLE(tupleConst = constant_) | ||
| 2663 | algorithm | ||
| 2664 | 2285 | res := propTupleAllConst(constant_); | |
| 2665 | then | ||
| 2666 | res; | ||
| 2667 | case prop | ||
| 2668 | algorithm | ||
| 2669 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 2670 | ✗ | Debug.trace("- prop_all_const failed: "); | |
| 2671 | ✗ | str := printPropStr(prop); | |
| 2672 | ✗ | Debug.traceln(str); | |
| 2673 | ✗ | then | |
| 2674 | fail(); | ||
| 2675 | end matchcontinue; | ||
| 2676 | end propAllConst; | ||
| 2677 | |||
| 2678 | public function propAnyConst "author: LS | ||
| 2679 | If PROP_TUPLE, returns true if any of the flags are true" | ||
| 2680 | input DAE.Properties inProperties; | ||
| 2681 | output DAE.Const outConst; | ||
| 2682 | algorithm | ||
| 2683 | outConst := matchcontinue inProperties | ||
| 2684 | local | ||
| 2685 | DAE.Const constant_,res; | ||
| 2686 | String str; | ||
| 2687 | DAE.Properties prop; | ||
| 2688 | DAE.TupleConst tconstant_; | ||
| 2689 | case DAE.PROP(constFlag = constant_) then constant_; | ||
| 2690 | case DAE.PROP_TUPLE(tupleConst = tconstant_) | ||
| 2691 | algorithm | ||
| 2692 | ✗ | res := propTupleAnyConst(tconstant_); | |
| 2693 | then | ||
| 2694 | res; | ||
| 2695 | case prop | ||
| 2696 | algorithm | ||
| 2697 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 2698 | ✗ | Debug.trace("- prop_any_const failed: "); | |
| 2699 | ✗ | str := printPropStr(prop); | |
| 2700 | ✗ | Debug.traceln(str); | |
| 2701 | ✗ | then | |
| 2702 | fail(); | ||
| 2703 | end matchcontinue; | ||
| 2704 | end propAnyConst; | ||
| 2705 | |||
| 2706 | protected function propTupleAnyConst "author: LS | ||
| 2707 | Helper function to prop_any_const." | ||
| 2708 | input DAE.TupleConst inTupleConst; | ||
| 2709 | output DAE.Const outConst; | ||
| 2710 | algorithm | ||
| 2711 | outConst := matchcontinue inTupleConst | ||
| 2712 | local | ||
| 2713 | DAE.Const c,res; | ||
| 2714 | DAE.TupleConst first,const; | ||
| 2715 | list<DAE.TupleConst> rest; | ||
| 2716 | String str; | ||
| 2717 | case DAE.SINGLE_CONST(const = c) then c; | ||
| 2718 | case DAE.TUPLE_CONST(tupleConstLst = (first :: _)) | ||
| 2719 | algorithm | ||
| 2720 | ✗ | DAE.C_CONST() := propTupleAnyConst(first); | |
| 2721 | then | ||
| 2722 | DAE.C_CONST(); | ||
| 2723 | case DAE.TUPLE_CONST(tupleConstLst = (first :: {})) | ||
| 2724 | algorithm | ||
| 2725 | ✗ | DAE.C_PARAM() := propTupleAnyConst(first); | |
| 2726 | then | ||
| 2727 | DAE.C_PARAM(); | ||
| 2728 | case DAE.TUPLE_CONST(tupleConstLst = (first :: {})) | ||
| 2729 | algorithm | ||
| 2730 | ✗ | DAE.C_VAR() := propTupleAnyConst(first); | |
| 2731 | then | ||
| 2732 | DAE.C_VAR(); | ||
| 2733 | case DAE.TUPLE_CONST(tupleConstLst = (first :: rest)) | ||
| 2734 | algorithm | ||
| 2735 | ✗ | DAE.C_PARAM() := propTupleAnyConst(first); | |
| 2736 | ✗ | res := propTupleAnyConst(DAE.TUPLE_CONST(rest)); | |
| 2737 | then | ||
| 2738 | res; | ||
| 2739 | case DAE.TUPLE_CONST(tupleConstLst = (first :: rest)) | ||
| 2740 | algorithm | ||
| 2741 | ✗ | DAE.C_VAR() := propTupleAnyConst(first); | |
| 2742 | ✗ | res := propTupleAnyConst(DAE.TUPLE_CONST(rest)); | |
| 2743 | then | ||
| 2744 | res; | ||
| 2745 | case const | ||
| 2746 | algorithm | ||
| 2747 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 2748 | ✗ | Debug.trace("- prop_tuple_any_const failed: "); | |
| 2749 | ✗ | str := TypesDump.printTupleConstStr(const); | |
| 2750 | ✗ | Debug.traceln(str); | |
| 2751 | ✗ | then | |
| 2752 | fail(); | ||
| 2753 | end matchcontinue; | ||
| 2754 | end propTupleAnyConst; | ||
| 2755 | |||
| 2756 | public function propTupleAllConst "author: LS | ||
| 2757 | Helper function to propAllConst." | ||
| 2758 | input DAE.TupleConst inTupleConst; | ||
| 2759 | output DAE.Const outConst; | ||
| 2760 | algorithm | ||
| 2761 | outConst := matchcontinue inTupleConst | ||
| 2762 | local | ||
| 2763 | DAE.Const c,res; | ||
| 2764 | DAE.TupleConst first,const; | ||
| 2765 | list<DAE.TupleConst> rest; | ||
| 2766 | String str; | ||
| 2767 | case DAE.SINGLE_CONST(const = c) then c; | ||
| 2768 | case DAE.TUPLE_CONST(tupleConstLst = (first :: _)) | ||
| 2769 | algorithm | ||
| 2770 |
2/2✓ Branch 1 taken 2585 times.
✓ Branch 2 taken 18 times.
|
2603 | DAE.C_PARAM() := propTupleAllConst(first); |
| 2771 | then | ||
| 2772 | DAE.C_PARAM(); | ||
| 2773 | case DAE.TUPLE_CONST(tupleConstLst = (first :: _)) | ||
| 2774 | algorithm | ||
| 2775 |
2/2✓ Branch 1 taken 438 times.
✓ Branch 2 taken 2147 times.
|
2585 | DAE.C_VAR() := propTupleAllConst(first); |
| 2776 | then | ||
| 2777 | DAE.C_VAR(); | ||
| 2778 | case DAE.TUPLE_CONST(tupleConstLst = (first :: {})) | ||
| 2779 | algorithm | ||
| 2780 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 166 times.
|
166 | DAE.C_CONST() := propTupleAllConst(first); |
| 2781 | then | ||
| 2782 | DAE.C_CONST(); | ||
| 2783 | case DAE.TUPLE_CONST(tupleConstLst = (first :: rest)) | ||
| 2784 | algorithm | ||
| 2785 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 272 times.
|
272 | DAE.C_CONST() := propTupleAllConst(first); |
| 2786 | 272 | res := propTupleAllConst(DAE.TUPLE_CONST(rest)); | |
| 2787 | then | ||
| 2788 | res; | ||
| 2789 | case const | ||
| 2790 | algorithm | ||
| 2791 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 2792 | ✗ | Debug.trace("- prop_tuple_all_const failed: "); | |
| 2793 | ✗ | str := TypesDump.printTupleConstStr(const); | |
| 2794 | ✗ | Debug.traceln(str); | |
| 2795 | ✗ | then | |
| 2796 | fail(); | ||
| 2797 | end matchcontinue; | ||
| 2798 | end propTupleAllConst; | ||
| 2799 | |||
| 2800 | public function isPropTupleArray "This function will check all elements in the tuple if anyone is an array, return true. | ||
| 2801 | As for now it will not check tuple of tuples ie. no recursion." | ||
| 2802 | input DAE.Properties p; | ||
| 2803 | output Boolean ob; | ||
| 2804 | protected | ||
| 2805 | Boolean b1,b2; | ||
| 2806 | algorithm | ||
| 2807 | 37698 | b1 := isPropTuple(p); | |
| 2808 | 37698 | b2 := isPropArray(p); | |
| 2809 | 37698 | ob := boolOr(b1,b2); | |
| 2810 | end isPropTupleArray; | ||
| 2811 | |||
| 2812 | public function isPropTuple | ||
| 2813 | "Checks if Properties is a tuple or not." | ||
| 2814 | input DAE.Properties p; | ||
| 2815 | output Boolean b; | ||
| 2816 | algorithm | ||
| 2817 | b := matchcontinue p | ||
| 2818 | case _ | ||
| 2819 | algorithm | ||
| 2820 |
2/2✓ Branch 1 taken 39125 times.
✓ Branch 2 taken 86 times.
|
39211 | DAE.T_TUPLE() := getPropType(p); |
| 2821 | then | ||
| 2822 | true; | ||
| 2823 | else false; | ||
| 2824 | end matchcontinue; | ||
| 2825 | end isPropTuple; | ||
| 2826 | |||
| 2827 | public function isPropArray "Return true if properties contain an array type." | ||
| 2828 | input DAE.Properties p; | ||
| 2829 | output Boolean b; | ||
| 2830 | protected | ||
| 2831 | Type t; | ||
| 2832 | algorithm | ||
| 2833 | 72804 | t := getPropType(p); | |
| 2834 | 72804 | b := isArray(t); | |
| 2835 | end isPropArray; | ||
| 2836 | |||
| 2837 | public function propTupleFirstProp | ||
| 2838 | "Returns the first property from a tuple's properties or fails." | ||
| 2839 | input DAE.Properties inTupleProp; | ||
| 2840 | output DAE.Properties outFirstProp; | ||
| 2841 | protected | ||
| 2842 | Type ty; | ||
| 2843 | DAE.Const c; | ||
| 2844 | algorithm | ||
| 2845 |
6/12✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
|
2 | DAE.PROP_TUPLE(type_ = DAE.T_TUPLE(types = ty :: _), |
| 2846 | tupleConst = DAE.TUPLE_CONST(tupleConstLst = DAE.SINGLE_CONST(const = c) :: _)) := inTupleProp; | ||
| 2847 | 2 | outFirstProp := DAE.PROP(ty, c); | |
| 2848 | end propTupleFirstProp; | ||
| 2849 | |||
| 2850 | public function propTuplePropList | ||
| 2851 | "Splits a PROP_TUPLE into a list of PROPs." | ||
| 2852 | input DAE.Properties prop_tuple; | ||
| 2853 | output list<DAE.Properties> prop_list; | ||
| 2854 | algorithm | ||
| 2855 | prop_list := match prop_tuple | ||
| 2856 | local | ||
| 2857 | list<DAE.Properties> pl; | ||
| 2858 | list<DAE.Type> tl; | ||
| 2859 | list<TupleConst> cl; | ||
| 2860 | case DAE.PROP_TUPLE(type_ = DAE.T_TUPLE(types = tl), | ||
| 2861 | tupleConst = DAE.TUPLE_CONST(tupleConstLst = cl)) | ||
| 2862 | algorithm | ||
| 2863 | 66 | pl := propTuplePropList2(tl, cl); | |
| 2864 | then | ||
| 2865 | pl; | ||
| 2866 | end match; | ||
| 2867 | end propTuplePropList; | ||
| 2868 | |||
| 2869 | protected function propTuplePropList2 | ||
| 2870 | "Helper function to propTuplePropList" | ||
| 2871 | input list<DAE.Type> tl; | ||
| 2872 | input list<TupleConst> cl; | ||
| 2873 | output list<DAE.Properties> pl; | ||
| 2874 | algorithm | ||
| 2875 | pl := match(tl, cl) | ||
| 2876 | local | ||
| 2877 | Type t; | ||
| 2878 | list<DAE.Type> t_rest; | ||
| 2879 | Const c; | ||
| 2880 | list<TupleConst> c_rest; | ||
| 2881 | list<DAE.Properties> p_rest; | ||
| 2882 | case ({}, {}) then {}; | ||
| 2883 | case (t :: t_rest, DAE.SINGLE_CONST(c) :: c_rest) | ||
| 2884 | algorithm | ||
| 2885 | 132 | p_rest := propTuplePropList2(t_rest, c_rest); | |
| 2886 | 132 | then | |
| 2887 | (DAE.PROP(t, c) :: p_rest); | ||
| 2888 | end match; | ||
| 2889 | end propTuplePropList2; | ||
| 2890 | |||
| 2891 | public function getPropConst "author: adrpo | ||
| 2892 | Return the const from Properties (no tuples!)." | ||
| 2893 | input DAE.Properties inProperties; | ||
| 2894 | output DAE.Const outConst; | ||
| 2895 | algorithm | ||
| 2896 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 681 times.
|
681 | DAE.PROP(constFlag = outConst) := inProperties; |
| 2897 | end getPropConst; | ||
| 2898 | |||
| 2899 | public function getPropType "author: LS | ||
| 2900 | Return the Type from Properties." | ||
| 2901 | input DAE.Properties inProperties; | ||
| 2902 | output DAE.Type outType; | ||
| 2903 | algorithm | ||
| 2904 | outType := match inProperties | ||
| 2905 | 1405172 | case DAE.PROP() then inProperties.type_; | |
| 2906 | 881 | case DAE.PROP_TUPLE() then inProperties.type_; | |
| 2907 | end match; | ||
| 2908 | end getPropType; | ||
| 2909 | |||
| 2910 | public function setPropType "Set the Type from Properties." | ||
| 2911 | input DAE.Properties inProperties; | ||
| 2912 | input DAE.Type ty; | ||
| 2913 | output DAE.Properties outProperties; | ||
| 2914 | algorithm | ||
| 2915 | outProperties := match inProperties | ||
| 2916 | 34082 | case DAE.PROP() then DAE.PROP(ty, inProperties.constFlag); | |
| 2917 | 108 | case DAE.PROP_TUPLE() then DAE.PROP_TUPLE(ty, inProperties.tupleConst); | |
| 2918 | end match; | ||
| 2919 | end setPropType; | ||
| 2920 | |||
| 2921 | public function createEmptyTypeMemory | ||
| 2922 | "@author: adrpo | ||
| 2923 | creates an array, with one element for each record in TType! | ||
| 2924 | Note: This has to be at least 4 larger than the number of records in DAE.Type, | ||
| 2925 | due to the way bootstrapping indexes records." | ||
| 2926 | output InstTypes.TypeMemoryEntryListArray tyMemory; | ||
| 2927 | algorithm | ||
| 2928 | ✗ | tyMemory := arrayCreate(30, {}); | |
| 2929 | end createEmptyTypeMemory; | ||
| 2930 | |||
| 2931 | public function simplifyType | ||
| 2932 | "@author: adrpo | ||
| 2933 | simplifies the given type, to be used in an expression or component reference" | ||
| 2934 | input DAE.Type inType; | ||
| 2935 | output DAE.Type outExpType; | ||
| 2936 | algorithm | ||
| 2937 | outExpType := matchcontinue inType | ||
| 2938 | local | ||
| 2939 | String str; | ||
| 2940 | Type t; | ||
| 2941 | DAE.Type t_1; | ||
| 2942 | DAE.Dimensions dims; | ||
| 2943 | list<DAE.Type> tys; | ||
| 2944 | list<DAE.Var> varLst; | ||
| 2945 | ClassInf.State CIS; | ||
| 2946 | DAE.EqualityConstraint ec; | ||
| 2947 | |||
| 2948 | 1826 | case DAE.T_FUNCTION() then DAE.T_FUNCTION_REFERENCE_VAR(inType); | |
| 2949 | |||
| 2950 | 320845 | case DAE.T_METAUNIONTYPE() then DAE.T_METATYPE(inType); | |
| 2951 | 5460 | case DAE.T_METARECORD() then DAE.T_METATYPE(inType); | |
| 2952 | 11847 | case DAE.T_METAPOLYMORPHIC() then DAE.T_METATYPE(inType); | |
| 2953 | 65995 | case DAE.T_METALIST() then DAE.T_METATYPE(inType); | |
| 2954 | 2500 | case DAE.T_METAARRAY() then DAE.T_METATYPE(inType); | |
| 2955 | 20144 | case DAE.T_METAOPTION() then DAE.T_METATYPE(inType); | |
| 2956 | 3542 | case DAE.T_METATUPLE() then DAE.T_METATYPE(inType); | |
| 2957 | |||
| 2958 | case DAE.T_UNKNOWN() then DAE.T_UNKNOWN_DEFAULT; | ||
| 2959 | case DAE.T_ANYTYPE() then DAE.T_UNKNOWN_DEFAULT; | ||
| 2960 | |||
| 2961 | case t as DAE.T_ARRAY() | ||
| 2962 | algorithm | ||
| 2963 | 1517901 | (t,dims) := TypesDump.flattenArrayType(t); | |
| 2964 | 1517901 | t_1 := simplifyType(t); | |
| 2965 | 1517901 | then | |
| 2966 | DAE.T_ARRAY(t_1,dims); | ||
| 2967 | |||
| 2968 | // do NOT simplify out equality constraint | ||
| 2969 | case DAE.T_SUBTYPE_BASIC(equalityConstraint = SOME(_)) then inType; | ||
| 2970 | 16454 | case DAE.T_SUBTYPE_BASIC(complexType = t) then simplifyType(t); | |
| 2971 | |||
| 2972 | case DAE.T_INTEGER() then DAE.T_INTEGER_DEFAULT; | ||
| 2973 | case DAE.T_REAL() then DAE.T_REAL_DEFAULT; | ||
| 2974 | case DAE.T_BOOL() then DAE.T_BOOL_DEFAULT; | ||
| 2975 | // BTH watch out: Due to simplification some type info is lost here | ||
| 2976 | case DAE.T_CLOCK() then DAE.T_CLOCK_DEFAULT; | ||
| 2977 | case DAE.T_STRING() then DAE.T_STRING_DEFAULT; | ||
| 2978 | case DAE.T_NORETCALL() then DAE.T_NORETCALL_DEFAULT; | ||
| 2979 | case DAE.T_TUPLE(types = tys) | ||
| 2980 | algorithm | ||
| 2981 | 1710 | tys := List.map(tys, simplifyType); | |
| 2982 | 1710 | then DAE.T_TUPLE(tys, inType.names); | |
| 2983 | |||
| 2984 | case DAE.T_ENUMERATION() then inType; | ||
| 2985 | |||
| 2986 | // for metamodelica we need this for some reson! | ||
| 2987 | case DAE.T_COMPLEX(CIS, varLst, ec) | ||
| 2988 | algorithm | ||
| 2989 |
2/2✓ Branch 1 taken 900428 times.
✓ Branch 2 taken 3126 times.
|
903554 | true := Config.acceptMetaModelicaGrammar(); |
| 2990 |
4/4✓ Branch 0 taken 726 times.
✓ Branch 1 taken 3126 times.
✓ Branch 2 taken 726 times.
✓ Branch 3 taken 3126 times.
|
3852 | varLst := list(simplifyVar(v) for v in varLst); |
| 2991 | 3126 | then | |
| 2992 | DAE.T_COMPLEX(CIS, varLst, ec, inType.usedExternally); | ||
| 2993 | |||
| 2994 | // do this for records too, otherwise: | ||
| 2995 | // frame.R = Modelica.Mechanics.MultiBody.Frames.Orientation({const_matrix); | ||
| 2996 | // does not get expanded into the component equations. | ||
| 2997 | case DAE.T_COMPLEX(CIS as ClassInf.RECORD(), varLst, ec) | ||
| 2998 | algorithm | ||
| 2999 |
4/4✓ Branch 0 taken 3250250 times.
✓ Branch 1 taken 316361 times.
✓ Branch 2 taken 3250250 times.
✓ Branch 3 taken 316361 times.
|
3566611 | varLst := list(simplifyVar(v) for v in varLst); |
| 3000 | 316361 | then | |
| 3001 | DAE.T_COMPLEX(CIS, varLst, ec, inType.usedExternally); | ||
| 3002 | |||
| 3003 | // otherwise just return the same! | ||
| 3004 | case DAE.T_COMPLEX() then inType; | ||
| 3005 | |||
| 3006 | case DAE.T_METABOXED(ty = t) | ||
| 3007 | algorithm | ||
| 3008 | 939 | t_1 := simplifyType(t); | |
| 3009 | 939 | then DAE.T_METABOXED(t_1); | |
| 3010 | |||
| 3011 | // This is the case when the type is currently UNTYPED | ||
| 3012 | case _ | ||
| 3013 | algorithm | ||
| 3014 | /* | ||
| 3015 | print(" untyped "); | ||
| 3016 | print(TypesDump.unparseType(inType)); | ||
| 3017 | print("\n"); | ||
| 3018 | */ | ||
| 3019 | then DAE.T_UNKNOWN_DEFAULT; | ||
| 3020 | |||
| 3021 | else | ||
| 3022 | algorithm | ||
| 3023 | ✗ | str := "Types.simplifyType failed for: " + TypesDump.unparseType(inType); | |
| 3024 | ✗ | Error.addMessage(Error.INTERNAL_ERROR, {str}); | |
| 3025 | ✗ | then fail(); | |
| 3026 | end matchcontinue; | ||
| 3027 | end simplifyType; | ||
| 3028 | |||
| 3029 | protected function simplifyVar | ||
| 3030 | input DAE.Var inVar; | ||
| 3031 | output DAE.Var outVar = inVar; | ||
| 3032 | algorithm | ||
| 3033 | outVar := match outVar | ||
| 3034 | case DAE.TYPES_VAR() | ||
| 3035 | algorithm | ||
| 3036 | 3250976 | outVar.ty := simplifyType(outVar.ty); | |
| 3037 | then | ||
| 3038 | outVar; | ||
| 3039 | end match; | ||
| 3040 | end simplifyVar; | ||
| 3041 | |||
| 3042 | public function complicateType | ||
| 3043 | "Does the opposite of simplifyType, as far as it's possible." | ||
| 3044 | input DAE.Type inType; | ||
| 3045 | output DAE.Type outType = inType; | ||
| 3046 | algorithm | ||
| 3047 | outType := match outType | ||
| 3048 | local | ||
| 3049 | DAE.Type ty; | ||
| 3050 | list<DAE.Dimension> dims; | ||
| 3051 | |||
| 3052 | case DAE.T_ARRAY(dims = _ :: _) | ||
| 3053 | algorithm | ||
| 3054 | 4296 | (ty, dims) := TypesDump.flattenArrayType(outType); | |
| 3055 | 4296 | then | |
| 3056 | liftArrayListDims(ty, dims); | ||
| 3057 | |||
| 3058 | ✗ | case DAE.T_FUNCTION_REFERENCE_VAR() then outType.functionType; | |
| 3059 | ✗ | case DAE.T_METATYPE() then outType.ty; | |
| 3060 | |||
| 3061 | case DAE.T_TUPLE() | ||
| 3062 | algorithm | ||
| 3063 | ✗ | outType.types := list(complicateType(t) for t in outType.types); | |
| 3064 | then | ||
| 3065 | outType; | ||
| 3066 | |||
| 3067 | case DAE.T_COMPLEX() | ||
| 3068 | algorithm | ||
| 3069 | ✗ | if isRecord(inType) or Config.acceptMetaModelicaGrammar() then | |
| 3070 | ✗ | outType.varLst := list(complicateVar(v) for v in outType.varLst); | |
| 3071 | end if; | ||
| 3072 | then | ||
| 3073 | outType; | ||
| 3074 | |||
| 3075 | case DAE.T_METABOXED() | ||
| 3076 | algorithm | ||
| 3077 | ✗ | outType.ty := complicateType(outType.ty); | |
| 3078 | then | ||
| 3079 | outType; | ||
| 3080 | |||
| 3081 | else outType; | ||
| 3082 | end match; | ||
| 3083 | end complicateType; | ||
| 3084 | |||
| 3085 | protected function complicateVar | ||
| 3086 | input DAE.Var inVar; | ||
| 3087 | output DAE.Var outVar = inVar; | ||
| 3088 | algorithm | ||
| 3089 | outVar := match outVar | ||
| 3090 | case DAE.TYPES_VAR() | ||
| 3091 | algorithm | ||
| 3092 | ✗ | outVar.ty := complicateType(outVar.ty); | |
| 3093 | then | ||
| 3094 | outVar; | ||
| 3095 | end match; | ||
| 3096 | end complicateVar; | ||
| 3097 | |||
| 3098 | protected function typeMemoryEntryEq | ||
| 3099 | input DAE.Type inType1; | ||
| 3100 | input tuple<DAE.Type, DAE.Type> inType2; | ||
| 3101 | output Boolean outEq; | ||
| 3102 | protected | ||
| 3103 | DAE.Type ty2; | ||
| 3104 | algorithm | ||
| 3105 | ✗ | (ty2, _) := inType2; | |
| 3106 | ✗ | outEq := typesElabEquivalent(inType1, ty2); | |
| 3107 | end typeMemoryEntryEq; | ||
| 3108 | |||
| 3109 | public function typesElabEquivalent | ||
| 3110 | "This function checks if two types will result in the same elaborated type. | ||
| 3111 | Used by simplifyType to check if a matching elaborated type already exists." | ||
| 3112 | input DAE.Type inType1; | ||
| 3113 | input DAE.Type inType2; | ||
| 3114 | output Boolean isEqual; | ||
| 3115 | algorithm | ||
| 3116 | try | ||
| 3117 | ✗ | isEqual := ttypesElabEquivalent(inType1, inType2); | |
| 3118 | else | ||
| 3119 | isEqual := false; | ||
| 3120 | end try; | ||
| 3121 | end typesElabEquivalent; | ||
| 3122 | |||
| 3123 | protected function ttypesElabEquivalent | ||
| 3124 | "Helper function to typesElabEquivalent. Checks if two TType will result in | ||
| 3125 | the same elaborated type." | ||
| 3126 | input DAE.Type inType1; | ||
| 3127 | input DAE.Type inType2; | ||
| 3128 | output Boolean isEqual; | ||
| 3129 | algorithm | ||
| 3130 | isEqual := match(inType1, inType2) | ||
| 3131 | local | ||
| 3132 | ClassInf.State cty1, cty2; | ||
| 3133 | list<DAE.Var> vars1, vars2; | ||
| 3134 | DAE.Dimension ad1, ad2; | ||
| 3135 | DAE.Type ty1, ty2; | ||
| 3136 | Absyn.Path p1, p2; | ||
| 3137 | list<String> names1, names2; | ||
| 3138 | list<DAE.Type> types1, types2; | ||
| 3139 | |||
| 3140 | case (DAE.T_COMPLEX(complexClassType = cty1, varLst = vars1), | ||
| 3141 | DAE.T_COMPLEX(complexClassType = cty2, varLst = vars2)) | ||
| 3142 | algorithm | ||
| 3143 | ✗ | true := AbsynUtil.pathEqual(ClassInfUtil.getStateName(cty1), | |
| 3144 | ClassInfUtil.getStateName(cty2)); | ||
| 3145 | ✗ | true := List.isEqualOnTrue(vars1, vars2, | |
| 3146 | varsElabEquivalent); | ||
| 3147 | then | ||
| 3148 | true; | ||
| 3149 | |||
| 3150 | case (DAE.T_ARRAY(dims = {ad1}, ty = ty1), | ||
| 3151 | DAE.T_ARRAY(dims = {ad2}, ty = ty2)) | ||
| 3152 | algorithm | ||
| 3153 | ✗ | true := valueEq(ad1, ad2); | |
| 3154 | ✗ | true := typesElabEquivalent(ty1, ty2); | |
| 3155 | then | ||
| 3156 | true; | ||
| 3157 | |||
| 3158 | case (DAE.T_ENUMERATION(path = p1, names = names1), | ||
| 3159 | DAE.T_ENUMERATION(path = p2, names = names2)) | ||
| 3160 | algorithm | ||
| 3161 | ✗ | true := AbsynUtil.pathEqual(p1, p2); | |
| 3162 | ✗ | true := List.isEqualOnTrue(names1, names2, stringEqual); | |
| 3163 | then | ||
| 3164 | true; | ||
| 3165 | |||
| 3166 | case (DAE.T_TUPLE(types = types1), | ||
| 3167 | DAE.T_TUPLE(types = types2)) | ||
| 3168 | ✗ | then List.isEqualOnTrue(types1, types2, | |
| 3169 | typesElabEquivalent); | ||
| 3170 | |||
| 3171 | case (DAE.T_METABOXED(ty = ty1), | ||
| 3172 | DAE.T_METABOXED(ty = ty2)) | ||
| 3173 | ✗ | then typesElabEquivalent(ty1, ty2); | |
| 3174 | |||
| 3175 | ✗ | else valueEq(inType1, inType2); | |
| 3176 | |||
| 3177 | end match; | ||
| 3178 | end ttypesElabEquivalent; | ||
| 3179 | |||
| 3180 | protected function varsElabEquivalent | ||
| 3181 | "Helper function to ttypesElabEquivalent. Check if two DAE.Var will result in | ||
| 3182 | the same DAE.Var after elaboration." | ||
| 3183 | input DAE.Var inVar1; | ||
| 3184 | input DAE.Var inVar2; | ||
| 3185 | output Boolean isEqual; | ||
| 3186 | algorithm | ||
| 3187 | isEqual := match(inVar1, inVar2) | ||
| 3188 | local | ||
| 3189 | DAE.Ident id1, id2; | ||
| 3190 | DAE.Type ty1, ty2; | ||
| 3191 | |||
| 3192 | case (DAE.TYPES_VAR(name = id1, ty = ty1), | ||
| 3193 | DAE.TYPES_VAR(name = id2, ty = ty2)) guard stringEqual(id1, id2) and typesElabEquivalent(ty1, ty2) | ||
| 3194 | then | ||
| 3195 | true; | ||
| 3196 | |||
| 3197 | else false; | ||
| 3198 | |||
| 3199 | end match; | ||
| 3200 | end varsElabEquivalent; | ||
| 3201 | |||
| 3202 | public function matchProp | ||
| 3203 | "This is basically a wrapper aroune matchType. | ||
| 3204 | It matches an expression with properties with another set of properties. | ||
| 3205 | If necessary, the expression is modified to match. | ||
| 3206 | The only relevant property is the type." | ||
| 3207 | input DAE.Exp inExp; | ||
| 3208 | input DAE.Properties inActualType; | ||
| 3209 | input DAE.Properties inExpectedType; | ||
| 3210 | input Boolean printFailtrace; | ||
| 3211 | output DAE.Exp outExp; | ||
| 3212 | output DAE.Properties outProperties; | ||
| 3213 | algorithm | ||
| 3214 | (outExp,outProperties) := matchcontinue (inExp, inActualType, inExpectedType, printFailtrace) | ||
| 3215 | local | ||
| 3216 | DAE.Exp e_1,e; | ||
| 3217 | Type t_1,gt,et; | ||
| 3218 | Const c,c1,c2,c_1; | ||
| 3219 | TupleConst tc,tc1,tc2; | ||
| 3220 | Properties prop; | ||
| 3221 | case (e,DAE.PROP(type_ = gt,constFlag = c1),DAE.PROP(type_ = et,constFlag = c2),_) | ||
| 3222 | algorithm | ||
| 3223 | 466101 | (e_1,t_1) := matchType(e, gt, et, printFailtrace); | |
| 3224 | 439481 | c := constAnd(c1, c2); | |
| 3225 | 439481 | then | |
| 3226 | (e_1,DAE.PROP(t_1,c)); | ||
| 3227 | case (e,DAE.PROP_TUPLE(type_ = gt,tupleConst = tc1),DAE.PROP_TUPLE(type_ = et,tupleConst = tc2),_) | ||
| 3228 | algorithm | ||
| 3229 | 46 | (e_1,t_1) := matchType(e, gt, et, printFailtrace); | |
| 3230 | 46 | tc := constTupleAnd(tc1, tc2); | |
| 3231 | 46 | then | |
| 3232 | (e_1,DAE.PROP_TUPLE(t_1,tc)); | ||
| 3233 | |||
| 3234 | // The problem with MetaModelica tuple is that it is a datatype (should use PROP instead of PROP_TUPLE) | ||
| 3235 | // this case converts a TUPLE to META_TUPLE | ||
| 3236 | case (e,DAE.PROP_TUPLE(type_ = gt as DAE.T_TUPLE(),tupleConst = tc1), DAE.PROP(type_ = et as DAE.T_METATUPLE(),constFlag = c2),_) | ||
| 3237 | algorithm | ||
| 3238 | ✗ | true := Config.acceptMetaModelicaGrammar(); | |
| 3239 | ✗ | (e_1,t_1) := matchType(e, gt, et, printFailtrace); | |
| 3240 | ✗ | c_1 := propTupleAllConst(tc1); | |
| 3241 | ✗ | c := constAnd(c_1, c2); | |
| 3242 | ✗ | then | |
| 3243 | (e_1,DAE.PROP(t_1,c)); | ||
| 3244 | case (e,DAE.PROP_TUPLE(type_ = gt as DAE.T_TUPLE(),tupleConst = tc1), DAE.PROP(type_ = et as DAE.T_METABOXED(),constFlag = c2),_) | ||
| 3245 | algorithm | ||
| 3246 | ✗ | true := Config.acceptMetaModelicaGrammar(); | |
| 3247 | ✗ | (e_1,t_1) := matchType(e, gt, et, printFailtrace); | |
| 3248 | ✗ | c_1 := propTupleAllConst(tc1); | |
| 3249 | ✗ | c := constAnd(c_1, c2); | |
| 3250 | ✗ | then | |
| 3251 | (e_1,DAE.PROP(t_1,c)); | ||
| 3252 | |||
| 3253 | case (e,DAE.PROP(type_ = gt),DAE.PROP_TUPLE(),_) | ||
| 3254 | algorithm | ||
| 3255 | ✗ | prop := propTupleFirstProp(inExpectedType); | |
| 3256 | ✗ | (e_1, prop) := matchProp(e, inActualType, prop, printFailtrace); | |
| 3257 | ✗ | gt := simplifyType(gt); | |
| 3258 | ✗ | e_1 := DAE.TSUB(e_1, 1, gt); | |
| 3259 | ✗ | then | |
| 3260 | (e_1, prop); | ||
| 3261 | |||
| 3262 | case (e,DAE.PROP_TUPLE(),DAE.PROP(),_) | ||
| 3263 | algorithm | ||
| 3264 | ✗ | prop as DAE.PROP(type_ = gt) := propTupleFirstProp(inActualType); | |
| 3265 | ✗ | (e_1, prop) := matchProp(e, prop, inExpectedType, printFailtrace); | |
| 3266 | ✗ | gt := simplifyType(gt); | |
| 3267 | ✗ | e_1 := DAE.TSUB(e_1, 1, gt); | |
| 3268 | ✗ | then | |
| 3269 | (e_1, prop); | ||
| 3270 | |||
| 3271 | case(e, _, _, true) | ||
| 3272 | algorithm | ||
| 3273 | // activate on -d=types flag | ||
| 3274 |
1/2✓ Branch 1 taken 18204 times.
✗ Branch 2 not taken.
|
18204 | true := Flags.isSet(Flags.TYPES); |
| 3275 | ✗ | Debug.traceln("- Types.matchProp failed on exp: " + ExpressionBasics.printExpStr(e)); | |
| 3276 | ✗ | Debug.traceln(printPropStr(inActualType) + " != "); | |
| 3277 | ✗ | Debug.traceln(printPropStr(inExpectedType)); | |
| 3278 | ✗ | then fail(); | |
| 3279 | end matchcontinue; | ||
| 3280 | end matchProp; | ||
| 3281 | |||
| 3282 | public function matchTypeList | ||
| 3283 | input list<DAE.Exp> exps; | ||
| 3284 | input DAE.Type expType; | ||
| 3285 | input DAE.Type expectedType; | ||
| 3286 | input Boolean printFailtrace; | ||
| 3287 | output list<DAE.Exp> outExp = {}; | ||
| 3288 | output list<DAE.Type> outTypeLst = {}; | ||
| 3289 | protected | ||
| 3290 | list<DAE.Exp> expLstNew = exps; | ||
| 3291 | DAE.Exp exp, e_1; | ||
| 3292 | Type tp; | ||
| 3293 | algorithm | ||
| 3294 |
2/2✓ Branch 0 taken 293 times.
✓ Branch 1 taken 112 times.
|
405 | while not listEmpty(expLstNew) loop |
| 3295 | 293 | exp::expLstNew := expLstNew; | |
| 3296 | 293 | (e_1, tp) := matchType(exp, expType, expectedType, printFailtrace); | |
| 3297 | outExp := e_1 :: outExp; | ||
| 3298 | 293 | outTypeLst := tp :: outTypeLst; | |
| 3299 | end while; | ||
| 3300 | 112 | outExp := listReverseInPlace(outExp); | |
| 3301 | 112 | outTypeLst := listReverseInPlace(outTypeLst); | |
| 3302 | end matchTypeList; | ||
| 3303 | |||
| 3304 | public function matchTypeTuple | ||
| 3305 | "Transforms a list of expressions and types into a list of expressions | ||
| 3306 | of the expected types." | ||
| 3307 | input list<DAE.Exp> inExp1; | ||
| 3308 | input list<DAE.Type> inTypeLst2; | ||
| 3309 | input list<DAE.Type> inTypeLst3; | ||
| 3310 | input Boolean printFailtrace; | ||
| 3311 | output list<DAE.Exp> outExp; | ||
| 3312 | output list<DAE.Type> outTypeLst; | ||
| 3313 | algorithm | ||
| 3314 | (outExp,outTypeLst):= | ||
| 3315 | matchcontinue (inExp1,inTypeLst2,inTypeLst3,printFailtrace) | ||
| 3316 | local | ||
| 3317 | DAE.Exp e,e_1; | ||
| 3318 | list<DAE.Exp> rest, e_2; | ||
| 3319 | Type tp,t1,t2; | ||
| 3320 | list<DAE.Type> res,ts1,ts2; | ||
| 3321 | case ({},{},{},_) then ({},{}); | ||
| 3322 | case (e::rest,(t1 :: ts1),(t2 :: ts2),_) | ||
| 3323 | algorithm | ||
| 3324 | 152999 | (e_1,tp) := matchType(e,t1,t2,printFailtrace); | |
| 3325 | 152999 | (e_2,res) := matchTypeTuple(rest,ts1,ts2,printFailtrace); | |
| 3326 | 152999 | then | |
| 3327 | (e_1::e_2,(tp :: res)); | ||
| 3328 | case (_,(t1 :: _),(t2 :: _),true) | ||
| 3329 | algorithm | ||
| 3330 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 3331 | ✗ | Debug.trace("- Types.matchTypeTuple failed:"+TypesDump.unparseType(t1)+" "+TypesDump.unparseType(t2)+"\n"); | |
| 3332 | ✗ | then | |
| 3333 | fail(); | ||
| 3334 | end matchcontinue; | ||
| 3335 | end matchTypeTuple; | ||
| 3336 | |||
| 3337 | public function matchTypeTupleCall | ||
| 3338 | input DAE.Exp inExp1; | ||
| 3339 | input list<DAE.Type> inTypeLst2; | ||
| 3340 | input list<DAE.Type> inTypeLst3; | ||
| 3341 | algorithm | ||
| 3342 | () := | ||
| 3343 | matchcontinue (inExp1,inTypeLst2,inTypeLst3) | ||
| 3344 | local | ||
| 3345 | DAE.Exp e; | ||
| 3346 | Type t1,t2; | ||
| 3347 | list<DAE.Type> ts1,ts2; | ||
| 3348 | case (_,_,{}) then (); | ||
| 3349 | case (e,(t1 :: ts1),(t2 :: ts2)) | ||
| 3350 | algorithm | ||
| 3351 | // We cannot use matchType here because it does not cast tuple calls properly | ||
| 3352 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2023 times.
|
2024 | true := subtype(t1, t2); |
| 3353 | /* (oe,_) = matchType(e, t1, t2, true); | ||
| 3354 | true = ExpressionBasics.expEqual(e,oe); */ | ||
| 3355 | 2023 | matchTypeTupleCall(e, ts1, ts2); | |
| 3356 | then (); | ||
| 3357 | case (_,(_ :: _),(_ :: _)) | ||
| 3358 | algorithm | ||
| 3359 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | true := Flags.isSet(Flags.FAILTRACE); |
| 3360 | ✗ | Debug.trace("- matchTypeTupleCall failed\n"); | |
| 3361 | ✗ | then | |
| 3362 | fail(); | ||
| 3363 | end matchcontinue; | ||
| 3364 | end matchTypeTupleCall; | ||
| 3365 | |||
| 3366 | public function vectorizableType "author: PA | ||
| 3367 | This function checks if a given type can be (converted and) vectorized to | ||
| 3368 | a expected type. | ||
| 3369 | For instance and argument of type Integer{:} can be vectorized to an | ||
| 3370 | argument type Real, using type coersion and vectorization of one dimension." | ||
| 3371 | input DAE.Exp inExp; | ||
| 3372 | input DAE.Type inExpType; | ||
| 3373 | input DAE.Type inExpectedType; | ||
| 3374 | input Option<Absyn.Path> fnPath; | ||
| 3375 | output DAE.Exp outExp; | ||
| 3376 | output DAE.Type outType; | ||
| 3377 | output DAE.Dimensions outArrayDimLst; | ||
| 3378 | output InstTypes.PolymorphicBindings outBindings; | ||
| 3379 | algorithm | ||
| 3380 | 3710 | (outExp,outType,outArrayDimLst,outBindings) := vectorizableType2(inExp,inExpType,inExpType,{},inExpectedType,fnPath); | |
| 3381 | end vectorizableType; | ||
| 3382 | |||
| 3383 | protected function vectorizableType2 | ||
| 3384 | input DAE.Exp inExp; | ||
| 3385 | input DAE.Type inExpType; | ||
| 3386 | input DAE.Type inCurrentType; | ||
| 3387 | input DAE.Dimensions inDims; | ||
| 3388 | input DAE.Type inExpectedType; | ||
| 3389 | input Option<Absyn.Path> fnPath; | ||
| 3390 | output DAE.Exp outExp; | ||
| 3391 | output DAE.Type outType; | ||
| 3392 | output DAE.Dimensions outDims; | ||
| 3393 | output InstTypes.PolymorphicBindings outBindings; | ||
| 3394 | protected | ||
| 3395 | Type vec_type, cur_type; | ||
| 3396 | DAE.Dimension dim; | ||
| 3397 | algorithm | ||
| 3398 | try | ||
| 3399 | 6624 | vec_type := liftArrayListDimsReverse(inExpectedType, inDims); | |
| 3400 | 6624 | (outExp, outType, outBindings) := | |
| 3401 | matchTypePolymorphic(inExp, inExpType, vec_type, fnPath, {}, true); | ||
| 3402 | 2885 | outDims := listReverse(inDims); | |
| 3403 | else | ||
| 3404 |
4/6✓ Branch 0 taken 825 times.
✓ Branch 1 taken 2914 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2914 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2914 times.
|
3739 | DAE.T_ARRAY(ty = cur_type, dims = {dim}) := inCurrentType; |
| 3405 | 2914 | (outExp, outType, outDims, outBindings) := | |
| 3406 | vectorizableType2(inExp, inExpType, cur_type, dim :: inDims, inExpectedType, fnPath); | ||
| 3407 | end try; | ||
| 3408 | end vectorizableType2; | ||
| 3409 | |||
| 3410 | public function unflattenArrayType | ||
| 3411 | "transforms T_ARRAY(a::b::c) to T_ARRAY(a, T_ARRAY(b, T_ARRAY(c))) | ||
| 3412 | Always call it with " | ||
| 3413 | input DAE.Type inTy; | ||
| 3414 | output DAE.Type outTy; | ||
| 3415 | algorithm | ||
| 3416 | 79520 | outTy := unflattenArrayType2(inTy, false); | |
| 3417 | end unflattenArrayType; | ||
| 3418 | |||
| 3419 | protected function unflattenArrayType2 | ||
| 3420 | "transforms T_ARRAY(a::b::c) to T_ARRAY(a, T_ARRAY(b, T_ARRAY(c))) | ||
| 3421 | Always call it with " | ||
| 3422 | input DAE.Type inTy; | ||
| 3423 | input Boolean last; | ||
| 3424 | output DAE.Type outTy; | ||
| 3425 | algorithm | ||
| 3426 | outTy := matchcontinue(inTy, last) | ||
| 3427 | local | ||
| 3428 | DAE.Type ty, t; | ||
| 3429 | DAE.Dimensions dims; | ||
| 3430 | DAE.Dimension dim; | ||
| 3431 | ClassInf.State ci; | ||
| 3432 | list<DAE.Var> vl; | ||
| 3433 | EqualityConstraint eqc; | ||
| 3434 | |||
| 3435 | // subtype basic crap | ||
| 3436 | case (DAE.T_SUBTYPE_BASIC(ci, vl, ty, eqc), _) | ||
| 3437 | algorithm | ||
| 3438 | ✗ | ty := unflattenArrayType(ty); | |
| 3439 | ✗ | then DAE.T_SUBTYPE_BASIC(ci, vl, ty, eqc); | |
| 3440 | |||
| 3441 | // already in the way we want it | ||
| 3442 | case (DAE.T_ARRAY(t, {dim}), _) | ||
| 3443 | algorithm | ||
| 3444 | 12573 | t := unflattenArrayType(t); | |
| 3445 | 12573 | then DAE.T_ARRAY(t, {dim}); | |
| 3446 | |||
| 3447 | // we might get here via true! | ||
| 3448 | case (DAE.T_ARRAY(t, {}), true) | ||
| 3449 | ✗ | then unflattenArrayType(t); | |
| 3450 | |||
| 3451 | // the usual case | ||
| 3452 | case (DAE.T_ARRAY(t, dim::dims), _) | ||
| 3453 | algorithm | ||
| 3454 | 6290 | ty := unflattenArrayType2(DAE.T_ARRAY(t, dims), true); | |
| 3455 | 6290 | ty := DAE.T_ARRAY(ty, {dim}); | |
| 3456 | then ty; | ||
| 3457 | |||
| 3458 | case (ty, false) then ty; | ||
| 3459 | end matchcontinue; | ||
| 3460 | end unflattenArrayType2; | ||
| 3461 | |||
| 3462 | protected function typeConvert | ||
| 3463 | "This functions converts the expression in the first argument to | ||
| 3464 | the type specified in the third argument. The current type of the | ||
| 3465 | expression is given in the second argument. | ||
| 3466 | If no type conversion is possible, this function fails." | ||
| 3467 | input DAE.Exp inExp1; | ||
| 3468 | input DAE.Type actual; | ||
| 3469 | input DAE.Type expected; | ||
| 3470 | input Boolean printFailtrace; | ||
| 3471 | output DAE.Exp outExp; | ||
| 3472 | output DAE.Type outType; | ||
| 3473 | algorithm | ||
| 3474 | (outExp,outType):= | ||
| 3475 | matchcontinue (inExp1, actual, expected) | ||
| 3476 | local | ||
| 3477 | list<DAE.Exp> elist_1,elist,inputs; | ||
| 3478 | DAE.Type at,t; | ||
| 3479 | Boolean sc, a; | ||
| 3480 | Integer nmax, oi; | ||
| 3481 | DAE.Dimension dim1, dim2, dim11, dim22; | ||
| 3482 | DAE.Dimensions dims; | ||
| 3483 | Type ty1,ty2,t1,t2,t_1,t_2,ty0,ty; | ||
| 3484 | DAE.Exp begin_1,step_1,stop_1,begin,step,stop,e_1,e,exp; | ||
| 3485 | list<list<DAE.Exp>> ell_1,ell,elist_big; | ||
| 3486 | list<DAE.Type> tys_1,tys1,tys2; | ||
| 3487 | String name; | ||
| 3488 | list<String> l; | ||
| 3489 | list<DAE.Var> v; | ||
| 3490 | Absyn.Path path,path1,path2; | ||
| 3491 | list<Absyn.Path> pathList; | ||
| 3492 | DAE.ComponentRef cref; | ||
| 3493 | list<DAE.ComponentRef> crefList; | ||
| 3494 | list<DAE.Type> expTypes; | ||
| 3495 | DAE.Type et,ety1; | ||
| 3496 | list<DAE.MatchCase> cases; | ||
| 3497 | DAE.MatchType matchTy; | ||
| 3498 | list<DAE.Element> localDecls; | ||
| 3499 | list<DAE.Var> els1,els2; | ||
| 3500 | Absyn.Path p1,p2,tp; | ||
| 3501 | list<list<String>> aliases; | ||
| 3502 | |||
| 3503 | // For the types that cannot be type-converted, but may be subtypes of another type | ||
| 3504 | case (e, ty1, ty2) | ||
| 3505 | algorithm | ||
| 3506 |
1/2✓ Branch 1 taken 949540 times.
✗ Branch 2 not taken.
|
949540 | true := subtype(ty1,ty2); |
| 3507 | ✗ | then (e, ty2); | |
| 3508 | |||
| 3509 | // if we expect notTuple and we get Tuple do DAE.TSUB(e, 1) | ||
| 3510 | // we try subtype of the first tuple element with the other type! | ||
| 3511 | case (e, DAE.T_TUPLE(types = ty1::_), ty2) | ||
| 3512 | algorithm | ||
| 3513 |
1/2✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
|
21 | false := Config.acceptMetaModelicaGrammar(); |
| 3514 | ✗ | false := isTuple(ty2); | |
| 3515 | ✗ | true := subtype(ty1, ty2); | |
| 3516 | ✗ | e := DAE.TSUB(e, 1, ty2); | |
| 3517 | ✗ | ty := ty2; | |
| 3518 | ✗ | then | |
| 3519 | (e, ty); | ||
| 3520 | |||
| 3521 | // try dims as list T_ARRAY(a::b::c) | ||
| 3522 | case (e, DAE.T_ARRAY(dims = _::_::_), ty2) | ||
| 3523 | algorithm | ||
| 3524 | ✗ | ty1 := unflattenArrayType(actual); | |
| 3525 | ✗ | ty2 := unflattenArrayType(ty2); | |
| 3526 | ✗ | (e, ty) := typeConvert(e, ty1, ty2, printFailtrace); | |
| 3527 | then | ||
| 3528 | (e, ty); | ||
| 3529 | |||
| 3530 | // try dims as list T_ARRAY(a::b::c) | ||
| 3531 | case (e, ty1, DAE.T_ARRAY(dims = _::_::_)) | ||
| 3532 | algorithm | ||
| 3533 | 21 | ty1 := unflattenArrayType(ty1); | |
| 3534 | 21 | ty2 := unflattenArrayType(expected); | |
| 3535 | 21 | (e, ty) := typeConvert(e, ty1, ty2, printFailtrace); | |
| 3536 | then | ||
| 3537 | (e, ty); | ||
| 3538 | |||
| 3539 | // Array expressions: expression dimension [dim1], expected dimension [dim2] | ||
| 3540 | case (DAE.ARRAY(array = elist), DAE.T_ARRAY(dims = {dim1},ty = ty1), ty0 as DAE.T_ARRAY(dims = {dim2},ty = ty2)) | ||
| 3541 | algorithm | ||
| 3542 |
2/2✓ Branch 1 taken 61339 times.
✓ Branch 2 taken 18058 times.
|
79397 | true := Expression.dimensionsKnownAndEqual(dim1, dim2); |
| 3543 | 18058 | elist_1 := typeConvertArray(elist,ty1,ty2,printFailtrace); | |
| 3544 | 16660 | at := simplifyType(ty0); | |
| 3545 | 16660 | a := isArray(ty2); | |
| 3546 | sc := boolNot(a); | ||
| 3547 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 16616 times.
|
33364 | then |
| 3548 | (DAE.ARRAY(at,sc,elist_1),DAE.T_ARRAY(ty2, {dim1})); | ||
| 3549 | |||
| 3550 | // Array expressions: expression dimension [:], expected dimension [dim2] | ||
| 3551 | /* ARRAYS HAVE KNOWN DIMENSIONS. WHO WROTE THIS :( | ||
| 3552 | case (DAE.ARRAY(array = elist), | ||
| 3553 | (DAE.T_ARRAY(dims = {DAE.DIM_UNKNOWN()},ty = ty1),_), | ||
| 3554 | ty0 as (DAE.T_ARRAY(dims = {dim2},ty = ty2),p2), | ||
| 3555 | printFailtrace) | ||
| 3556 | algorithm | ||
| 3557 | true = Expression.dimensionKnown(dim2); | ||
| 3558 | elist_1 = typeConvertArray(elist,ty1,ty2,printFailtrace); | ||
| 3559 | at = simplifyType(ty0); | ||
| 3560 | a = isArray(ty2); | ||
| 3561 | sc = boolNot(a); | ||
| 3562 | then | ||
| 3563 | (DAE.ARRAY(at,sc,elist_1),(DAE.T_ARRAY(DAE.DIM_UNKNOWN(),ty2),p2)); | ||
| 3564 | */ | ||
| 3565 | |||
| 3566 | // Array expressions: expression dimension [dim1], expected dimension [:] | ||
| 3567 | case (DAE.ARRAY(array = elist), DAE.T_ARRAY(dims = {dim1},ty = ty1), DAE.T_ARRAY(dims = {DAE.DIM_UNKNOWN()}, ty = ty2)) | ||
| 3568 | algorithm | ||
| 3569 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 61338 times.
|
61338 | true := Expression.dimensionKnown(dim1); |
| 3570 | 61338 | elist_1 := typeConvertArray(elist,ty1,ty2,printFailtrace); | |
| 3571 | 424 | dims := Expression.arrayDimension(simplifyType(ty1)); | |
| 3572 | 424 | a := isArray(ty2); | |
| 3573 | sc := boolNot(a); | ||
| 3574 | dims := dim1 :: dims; | ||
| 3575 | 424 | ty2 := arrayElementType(ty2); | |
| 3576 | 424 | ety1 := simplifyType(ty2); | |
| 3577 | 424 | ty2 := liftArrayListDims(ty2, dims); | |
| 3578 | //TODO: Verify correctness of return value. | ||
| 3579 |
2/2✓ Branch 1 taken 68 times.
✓ Branch 2 taken 356 times.
|
492 | then |
| 3580 | (DAE.ARRAY(DAE.T_ARRAY(ety1, dims),sc,elist_1), ty2); | ||
| 3581 | |||
| 3582 | // Full range expressions, e.g. 1:2:10 | ||
| 3583 | case (DAE.RANGE(start = begin,step = SOME(step),stop = stop), DAE.T_ARRAY(dims = {dim1},ty = ty1), DAE.T_ARRAY(dims = {dim2}, ty = ty2)) | ||
| 3584 | algorithm | ||
| 3585 | ✗ | true := Expression.dimensionsKnownAndEqual(dim1, dim2); | |
| 3586 | ✗ | (begin_1,_) := typeConvert(begin, ty1, ty2, printFailtrace); | |
| 3587 | ✗ | (step_1,_) := typeConvert(step, ty1, ty2, printFailtrace); | |
| 3588 | ✗ | (stop_1,_) := typeConvert(stop, ty1, ty2, printFailtrace); | |
| 3589 | ✗ | at := simplifyType(DAE.T_ARRAY(ty2, {dim1})); | |
| 3590 | ✗ | then | |
| 3591 | (DAE.RANGE(at,begin_1,SOME(step_1),stop_1), DAE.T_ARRAY(ty2, {dim1})); | ||
| 3592 | |||
| 3593 | // Range expressions, e.g. 1:10 | ||
| 3594 | case (DAE.RANGE(start = begin,step = NONE(),stop = stop), DAE.T_ARRAY(dims = {dim1}, ty = ty1), DAE.T_ARRAY(dims = {dim2}, ty = ty2)) | ||
| 3595 | algorithm | ||
| 3596 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 time.
|
7 | true := Expression.dimensionsKnownAndEqual(dim1, dim2); |
| 3597 | 1 | (begin_1,_) := typeConvert(begin, ty1, ty2, printFailtrace); | |
| 3598 | 1 | (stop_1,_) := typeConvert(stop, ty1, ty2, printFailtrace); | |
| 3599 | 1 | at := simplifyType(DAE.T_ARRAY(ty2, {dim1})); | |
| 3600 | 2 | then | |
| 3601 | (DAE.RANGE(at,begin_1,NONE(),stop_1), DAE.T_ARRAY(ty2, {dim1})); | ||
| 3602 | |||
| 3603 | // Matrix expressions: expression dimension [dim1,dim11], expected dimension [dim2,dim22] | ||
| 3604 | case (DAE.MATRIX(integer = nmax,matrix = ell), DAE.T_ARRAY(dims = {dim1},ty = DAE.T_ARRAY(dims = {dim11},ty = t1)), ty0 as DAE.T_ARRAY(dims = {dim2},ty = DAE.T_ARRAY(dims = {dim22},ty = t2))) | ||
| 3605 | algorithm | ||
| 3606 |
2/2✓ Branch 1 taken 9494 times.
✓ Branch 2 taken 141 times.
|
9635 | true := Expression.dimensionsKnownAndEqual(dim1, dim2); |
| 3607 |
2/2✓ Branch 1 taken 9 times.
✓ Branch 2 taken 132 times.
|
141 | true := Expression.dimensionsKnownAndEqual(dim11, dim22); |
| 3608 | 132 | ell_1 := typeConvertMatrix(ell,t1,t2,printFailtrace); | |
| 3609 | 122 | at := simplifyType(ty0); | |
| 3610 | 366 | then | |
| 3611 | (DAE.MATRIX(at,nmax,ell_1),DAE.T_ARRAY(DAE.T_ARRAY(t2,{dim11}),{dim1})); | ||
| 3612 | |||
| 3613 | // Matrix expressions: expression dimension [dim1,dim11] expected dimension [:,dim22] | ||
| 3614 | case (DAE.MATRIX(integer = nmax,matrix = ell), DAE.T_ARRAY(dims = {dim1},ty = DAE.T_ARRAY(dims = {dim11},ty = t1)), DAE.T_ARRAY(dims = {dim2},ty = DAE.T_ARRAY(dims = {dim22},ty = t2))) | ||
| 3615 | guard not Expression.dimensionKnown(dim2) | ||
| 3616 | algorithm | ||
| 3617 |
2/2✓ Branch 1 taken 9489 times.
✓ Branch 2 taken 3 times.
|
9492 | true := Expression.dimensionsKnownAndEqual(dim11, dim22); |
| 3618 | 3 | ell_1 := typeConvertMatrix(ell,t1,t2,printFailtrace); | |
| 3619 | 6 | ty := DAE.T_ARRAY(DAE.T_ARRAY(t2,{dim11}),{dim1}); | |
| 3620 | 3 | at := simplifyType(ty); | |
| 3621 | 3 | then | |
| 3622 | (DAE.MATRIX(at,nmax,ell_1),ty); | ||
| 3623 | |||
| 3624 | // Arbitrary expressions, expression dimension [dim1], expected dimension [dim2] | ||
| 3625 | case (e, DAE.T_ARRAY(dims = {dim1},ty = ty1), DAE.T_ARRAY(dims = {dim2},ty = ty2)) | ||
| 3626 | algorithm | ||
| 3627 |
2/2✓ Branch 1 taken 108688 times.
✓ Branch 2 taken 1556 times.
|
110244 | true := Expression.dimensionsKnownAndEqual(dim1, dim2); |
| 3628 | 1556 | (e_1,t_1) := typeConvert(e, ty1, ty2, printFailtrace); | |
| 3629 | 133 | e_1 := liftExpType(e_1,dim1); | |
| 3630 | 133 | t_2 := DAE.T_ARRAY(t_1,{dim2}); | |
| 3631 | 133 | then | |
| 3632 | (e_1,t_2); | ||
| 3633 | |||
| 3634 | // Arbitrary expressions, expression dimension [:], expected dimension [dim2] | ||
| 3635 | case (e, DAE.T_ARRAY(dims = {DAE.DIM_UNKNOWN()},ty = ty1), DAE.T_ARRAY(dims = {_},ty = ty2)) | ||
| 3636 | algorithm | ||
| 3637 | 828 | (e_1,t_1) := typeConvert(e, ty1, ty2, printFailtrace); | |
| 3638 | 22 | e_1 := liftExpType(e_1,DAE.DIM_UNKNOWN()); | |
| 3639 | 22 | then | |
| 3640 | (e_1,DAE.T_ARRAY(t_1,{DAE.DIM_UNKNOWN()})); | ||
| 3641 | |||
| 3642 | // Arbitrary expression, expression dimension [dim1] expected dimension [:] | ||
| 3643 | case (e, DAE.T_ARRAY(dims = {dim1},ty = ty1), DAE.T_ARRAY(dims = {DAE.DIM_UNKNOWN()},ty = ty2)) | ||
| 3644 | algorithm | ||
| 3645 | 108662 | (e_1,t_1) := typeConvert(e, ty1, ty2, printFailtrace); | |
| 3646 | 184 | e_1 := liftExpType(e_1,dim1); | |
| 3647 | 184 | then | |
| 3648 | (e_1,DAE.T_ARRAY(t_1,{dim1})); | ||
| 3649 | |||
| 3650 | // Arbitrary expressions, expression dimension [:] expected dimension [:] | ||
| 3651 | case (e, DAE.T_ARRAY(dims = {dim1},ty = ty1), DAE.T_ARRAY(dims = {dim2},ty = ty2)) | ||
| 3652 | algorithm | ||
| 3653 |
2/2✓ Branch 1 taken 109018 times.
✓ Branch 2 taken 887 times.
|
109905 | false := Expression.dimensionKnown(dim1); |
| 3654 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 887 times.
|
887 | false := Expression.dimensionKnown(dim2); |
| 3655 | 887 | (e_1,t_1) := typeConvert(e, ty1, ty2, printFailtrace); | |
| 3656 | ✗ | e_1 := liftExpType(e_1,DAE.DIM_UNKNOWN()); | |
| 3657 | ✗ | then | |
| 3658 | (e_1,DAE.T_ARRAY(t_1,{DAE.DIM_UNKNOWN()})); | ||
| 3659 | |||
| 3660 | // Tuple | ||
| 3661 | case (DAE.TUPLE(PR = elist), DAE.T_TUPLE(types = tys1), DAE.T_TUPLE(types = tys2)) | ||
| 3662 | algorithm | ||
| 3663 | ✗ | (elist_1,tys_1) := typeConvertList(elist, tys1, tys2, printFailtrace); | |
| 3664 | ✗ | then | |
| 3665 | (DAE.TUPLE(elist_1),DAE.T_TUPLE(tys_1,expected.names)); | ||
| 3666 | |||
| 3667 | // Implicit conversion from Integer literal to an enumeration | ||
| 3668 | // This is not a valid Modelica conversion, but was widely used in the past, | ||
| 3669 | // by, for instance, Modelica.Electrical.Digital. | ||
| 3670 | // Enable with --intEnumConversion. | ||
| 3671 | case (exp as DAE.ICONST(oi), DAE.T_INTEGER(), t2 as DAE.T_ENUMERATION(path = tp, names = l)) | ||
| 3672 | algorithm | ||
| 3673 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 7 times.
|
8 | true := Config.intEnumConversion(); |
| 3674 | // It would be good to have the source location of exp here, so that we could pass it to typeConvertIntToEnumCheck. | ||
| 3675 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
|
7 | true := typeConvertIntToEnumCheck(exp, t2); // Will warn or report error depending on whether oi is out of range. |
| 3676 | // select from enum list: | ||
| 3677 | 7 | name := listGet(l, oi); | |
| 3678 | 7 | tp := AbsynUtil.joinPaths(tp, Absyn.IDENT(name)); | |
| 3679 | 7 | then | |
| 3680 | (DAE.ENUM_LITERAL(tp, oi),expected); | ||
| 3681 | |||
| 3682 | // Implicit conversion from Integer to Real | ||
| 3683 | case (e, DAE.T_INTEGER(), DAE.T_REAL()) | ||
| 3684 | 252963 | then | |
| 3685 | (DAE.CAST(DAE.T_REAL_DEFAULT,e),expected); | ||
| 3686 | |||
| 3687 | // Complex type inheriting primitive type | ||
| 3688 | case (e, DAE.T_SUBTYPE_BASIC(complexType = t1), t2) algorithm | ||
| 3689 | 19 | (e_1,t_1) := typeConvert(e,t1,t2,printFailtrace); | |
| 3690 | then (e_1,t_1); | ||
| 3691 | case (e, t1, DAE.T_SUBTYPE_BASIC(complexType = t2)) algorithm | ||
| 3692 | 1368 | (e_1,t_1) := typeConvert(e,t1,t2,printFailtrace); | |
| 3693 | then (e_1,t_1); | ||
| 3694 | |||
| 3695 | // Complex types (records) that need a cast | ||
| 3696 | case (e, DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(p1),varLst = els1), t2 as DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(p2),varLst = els2)) | ||
| 3697 | algorithm | ||
| 3698 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4602 times.
|
4602 | false := AbsynUtil.pathEqual(p1,p2) "We need to add a cast from one record to another"; |
| 3699 |
2/4✓ Branch 1 taken 4602 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 4602 times.
|
4602 | true := Flags.isSet(Flags.ALLOW_RECORD_TOO_MANY_FIELDS) or (listLength(els1) == listLength(els2)); |
| 3700 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4602 times.
|
4602 | true := subtypeVarlist(els1, els2); |
| 3701 | 4602 | e := DAE.CAST(t2, e); | |
| 3702 | 4602 | then (e, t2); | |
| 3703 | |||
| 3704 | // MetaModelica Option | ||
| 3705 | case (DAE.META_OPTION(SOME(e)), DAE.T_METAOPTION(ty = t1), DAE.T_METAOPTION(t2)) guard Config.acceptMetaModelicaGrammar() | ||
| 3706 | algorithm | ||
| 3707 | ✗ | (e_1, t_1) := matchType(e,t1,t2,printFailtrace); | |
| 3708 | ✗ | then | |
| 3709 | (DAE.META_OPTION(SOME(e_1)),DAE.T_METAOPTION(t_1)); | ||
| 3710 | |||
| 3711 | case (DAE.META_OPTION(NONE()), _, DAE.T_METAOPTION(t2)) guard Config.acceptMetaModelicaGrammar() | ||
| 3712 | ✗ | then | |
| 3713 | (DAE.META_OPTION(NONE()),DAE.T_METAOPTION(t2)); | ||
| 3714 | |||
| 3715 | // MetaModelica Tuple | ||
| 3716 | case (DAE.TUPLE(elist), DAE.T_TUPLE(types = tys1), DAE.T_METATUPLE(tys2)) guard Config.acceptMetaModelicaGrammar() | ||
| 3717 | algorithm | ||
| 3718 | 18 | tys2 := List.map(tys2, boxIfUnboxedType); | |
| 3719 | 18 | (elist_1,tys_1) := matchTypeTuple(elist, tys1, tys2, printFailtrace); | |
| 3720 | 18 | then | |
| 3721 | (DAE.META_TUPLE(elist_1),DAE.T_METATUPLE(tys_1)); | ||
| 3722 | |||
| 3723 | case (DAE.MATCHEXPRESSION(matchTy,inputs,aliases,localDecls,cases,et), _, _) | ||
| 3724 | algorithm | ||
| 3725 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | true := Config.acceptMetaModelicaGrammar(); |
| 3726 | 3 | elist := resultExps(cases); | |
| 3727 | 3 | (elist_1,_) := matchTypeList(elist, actual, expected, printFailtrace); | |
| 3728 | 3 | cases:=fixCaseReturnTypes2(cases,elist_1,Absyn.dummyInfo); | |
| 3729 | 3 | et:=simplifyType(expected); | |
| 3730 | 3 | then | |
| 3731 | (DAE.MATCHEXPRESSION(matchTy,inputs,aliases,localDecls,cases,et),expected); | ||
| 3732 | |||
| 3733 | case (DAE.META_TUPLE(elist), DAE.T_METATUPLE(types = tys1), DAE.T_METATUPLE(tys2)) | ||
| 3734 | algorithm | ||
| 3735 | ✗ | tys2 := List.map(tys2, boxIfUnboxedType); | |
| 3736 | ✗ | (elist_1,tys_1) := matchTypeTuple(elist, tys1, tys2, printFailtrace); | |
| 3737 | ✗ | then | |
| 3738 | (DAE.META_TUPLE(elist_1),DAE.T_METATUPLE(tys_1)); | ||
| 3739 | |||
| 3740 | case (DAE.TUPLE(elist), DAE.T_TUPLE(types = tys1), ty2 as DAE.T_METABOXED(ty = DAE.T_UNKNOWN())) | ||
| 3741 | algorithm | ||
| 3742 | ✗ | true := Config.acceptMetaModelicaGrammar(); | |
| 3743 | ✗ | tys2 := List.fill(ty2, listLength(tys1)); | |
| 3744 | ✗ | (elist_1,tys_1) := matchTypeTuple(elist, tys1, tys2, printFailtrace); | |
| 3745 | ✗ | then | |
| 3746 | (DAE.META_TUPLE(elist_1),DAE.T_METATUPLE(tys_1)); | ||
| 3747 | |||
| 3748 | // The automatic type conversion will convert any array that can be | ||
| 3749 | // const-eval'ed to an DAE.ARRAY or DAE.MATRIX into a list of the same | ||
| 3750 | // type. The reason is that the syntax for the array and list constructor | ||
| 3751 | // is the same. However, the compiler can't distinguish between the two | ||
| 3752 | // cases below because a is expanded earlier in the compilation process: | ||
| 3753 | // Integer[3] a; | ||
| 3754 | // someListFunction(a); // Is expanded to the line below | ||
| 3755 | // someListFunction({a[1],a[2],a[3]}); | ||
| 3756 | // / sjoelund 2009-08-13 | ||
| 3757 | case (DAE.ARRAY(DAE.T_ARRAY(),_,elist), DAE.T_ARRAY(ty=t1), DAE.T_METALIST(t2)) | ||
| 3758 | algorithm | ||
| 3759 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
|
43 | true := Config.acceptMetaModelicaGrammar(); |
| 3760 | 43 | t2 := boxIfUnboxedType(t2); | |
| 3761 | 43 | (elist_1, _) := matchTypeList(elist, t1, t2, printFailtrace); | |
| 3762 | 43 | e_1 := DAE.LIST(elist_1); | |
| 3763 | 43 | t2 := DAE.T_METALIST(t2); | |
| 3764 | 43 | then (e_1, t2); | |
| 3765 | |||
| 3766 | case (DAE.ARRAY(DAE.T_ARRAY(),_,elist), DAE.T_ARRAY(ty=t1), DAE.T_METABOXED(t2)) | ||
| 3767 | algorithm | ||
| 3768 |
2/2✓ Branch 1 taken 155 times.
✓ Branch 2 taken 21 times.
|
176 | true := Config.acceptMetaModelicaGrammar(); |
| 3769 | 21 | (elist_1, tys1) := matchTypeList(elist, t1, t2, printFailtrace); | |
| 3770 | 21 | (elist_1, t2) := listMatchSuperType(elist_1, tys1, printFailtrace); | |
| 3771 | 21 | t2 := boxIfUnboxedType(t2); | |
| 3772 | 21 | (elist_1, _) := matchTypeList(elist_1, t1, t2, printFailtrace); | |
| 3773 | 21 | e_1 := DAE.LIST(elist_1); | |
| 3774 | 21 | t2 := DAE.T_METALIST(t2); | |
| 3775 | 21 | then (e_1, t2); | |
| 3776 | |||
| 3777 | case (DAE.MATRIX(DAE.T_ARRAY(),_,elist_big), t1, t2) | ||
| 3778 | algorithm | ||
| 3779 |
2/2✓ Branch 1 taken 37283 times.
✓ Branch 2 taken 12 times.
|
37295 | true := Config.acceptMetaModelicaGrammar(); |
| 3780 | 12 | (elist,ty2) := typeConvertMatrixToList(elist_big,t1,t2,printFailtrace); | |
| 3781 | 12 | e_1 := DAE.LIST(elist); | |
| 3782 | 12 | then (e_1,ty2); | |
| 3783 | |||
| 3784 | case (DAE.LIST(elist), DAE.T_METALIST(ty = t1), DAE.T_METALIST(t2)) | ||
| 3785 | algorithm | ||
| 3786 | ✗ | true := Config.acceptMetaModelicaGrammar(); | |
| 3787 | ✗ | (elist_1, tys1) := matchTypeList(elist, t1, t2, printFailtrace); | |
| 3788 | ✗ | (elist_1, t2) := listMatchSuperType(elist_1, tys1, printFailtrace); | |
| 3789 | ✗ | e_1 := DAE.LIST(elist_1); | |
| 3790 | ✗ | t2 := DAE.T_METALIST(t2); | |
| 3791 | ✗ | then (e_1, t2); | |
| 3792 | |||
| 3793 | case (e, t1 as DAE.T_INTEGER(), DAE.T_METABOXED(ty = t2)) | ||
| 3794 | algorithm | ||
| 3795 | 20518 | (e,t1) := matchType(e,t1,unboxedType(t2),printFailtrace); | |
| 3796 | 20518 | t2 := DAE.T_METABOXED(t1); | |
| 3797 | 20518 | e := Expression.boxExp(e); | |
| 3798 | 20518 | then (e,t2); | |
| 3799 | |||
| 3800 | case (e, t1 as DAE.T_BOOL(), DAE.T_METABOXED(ty = t2)) | ||
| 3801 | algorithm | ||
| 3802 | 13836 | (e,t1) := matchType(e,t1,unboxedType(t2),printFailtrace); | |
| 3803 | 13836 | t2 := DAE.T_METABOXED(t1); | |
| 3804 | 13836 | e := Expression.boxExp(e); | |
| 3805 | 13836 | then (e,t2); | |
| 3806 | |||
| 3807 | case (e, t1 as DAE.T_REAL(), DAE.T_METABOXED(ty = t2)) | ||
| 3808 | algorithm | ||
| 3809 | 866 | (e,t1) := matchType(e,t1,unboxedType(t2),printFailtrace); | |
| 3810 | 866 | t2 := DAE.T_METABOXED(t1); | |
| 3811 | 866 | e := Expression.boxExp(e); | |
| 3812 | 866 | then (e,t2); | |
| 3813 | |||
| 3814 | case (e, t1 as DAE.T_ENUMERATION(), DAE.T_METABOXED(ty = t2)) | ||
| 3815 | algorithm | ||
| 3816 | 964 | (e, t1) := matchType(e, t1, unboxedType(t2), printFailtrace); | |
| 3817 | 964 | t2 := DAE.T_METABOXED(t1); | |
| 3818 | 964 | e := Expression.boxExp(e); | |
| 3819 | 964 | then | |
| 3820 | (e, t2); | ||
| 3821 | |||
| 3822 | case (e, t1 as DAE.T_ARRAY(), DAE.T_METABOXED(ty = t2)) | ||
| 3823 | algorithm | ||
| 3824 | 162 | (e, t1) := matchType(e, t1, unboxedType(t2), printFailtrace); | |
| 3825 | 162 | t2 := DAE.T_METABOXED(t1); | |
| 3826 | 162 | e := Expression.boxExp(e); | |
| 3827 | 162 | then | |
| 3828 | (e, t2); | ||
| 3829 | |||
| 3830 | case (DAE.CALL(path = path1, expLst = elist), t1 as DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(path2), varLst = v), DAE.T_METABOXED(ty = t2)) | ||
| 3831 | algorithm | ||
| 3832 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | true := subtype(t1,t2); |
| 3833 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | true := AbsynUtil.pathEqual(path1, path2); |
| 3834 | 2 | t2 := DAE.T_METABOXED(t1); | |
| 3835 | 2 | l := List.map(v, TypesDump.getVarName); | |
| 3836 | 2 | tys1 := List.map(v, getVarType); | |
| 3837 | 2 | tys2 := List.map(tys1, boxIfUnboxedType); | |
| 3838 | 2 | (elist,_) := matchTypeTuple(elist, tys1, tys2, printFailtrace); | |
| 3839 | 2 | e_1 := DAE.METARECORDCALL(path1, elist, l, -1, {}); | |
| 3840 | 2 | then (e_1,t2); | |
| 3841 | |||
| 3842 | case (DAE.RECORD(path = path1, exps = elist), t1 as DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(path2), varLst = v), DAE.T_METABOXED(ty = t2)) | ||
| 3843 | algorithm | ||
| 3844 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | true := subtype(t1,t2); |
| 3845 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | true := AbsynUtil.pathEqual(path1, path2); |
| 3846 | 8 | t2 := DAE.T_METABOXED(t1); | |
| 3847 | 8 | l := List.map(v, TypesDump.getVarName); | |
| 3848 | 8 | tys1 := List.map(v, getVarType); | |
| 3849 | 8 | tys2 := List.map(tys1, boxIfUnboxedType); | |
| 3850 | 8 | (elist,_) := matchTypeTuple(elist, tys1, tys2, printFailtrace); | |
| 3851 | 8 | e_1 := DAE.METARECORDCALL(path1, elist, l, -1, {}); | |
| 3852 | 8 | then (e_1,t2); | |
| 3853 | |||
| 3854 | case (DAE.CREF(cref,_), t1 as DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(path), varLst = v), DAE.T_METABOXED(ty = t2)) | ||
| 3855 | algorithm | ||
| 3856 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
|
21 | true := subtype(t1,t2); |
| 3857 | 21 | t2 := DAE.T_METABOXED(t1); | |
| 3858 | 21 | l := List.map(v, TypesDump.getVarName); | |
| 3859 | 21 | tys1 := List.map(v, getVarType); | |
| 3860 | 21 | tys2 := List.map(tys1, boxIfUnboxedType); | |
| 3861 | 21 | expTypes := List.map(tys1, simplifyType); | |
| 3862 | 21 | pathList := List.map(l, AbsynUtil.makeIdentPathFromString); | |
| 3863 | 21 | crefList := List.map(pathList, ComponentReference.pathToCref); | |
| 3864 | 21 | crefList := List.map1r(crefList, ComponentReference.joinCrefs, cref); | |
| 3865 | 21 | elist := List.threadMap(crefList, expTypes, Expression.makeCrefExp); | |
| 3866 | 21 | (elist,_) := matchTypeTuple(elist, tys1, tys2, printFailtrace); | |
| 3867 | 21 | e_1 := DAE.METARECORDCALL(path, elist, l, -1, {}); | |
| 3868 | 21 | then (e_1,t2); | |
| 3869 | |||
| 3870 | case (e, DAE.T_COMPLEX(complexClassType = ClassInf.RECORD()), DAE.T_METABOXED()) | ||
| 3871 | algorithm | ||
| 3872 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 3873 | ✗ | Debug.trace("- Not yet implemented: Converting record into boxed records: "+ExpressionBasics.printExpStr(e)+"\n"); | |
| 3874 | ✗ | then | |
| 3875 | fail(); | ||
| 3876 | |||
| 3877 | case (DAE.BOX(e), DAE.T_METABOXED(ty = t1), t2) | ||
| 3878 | algorithm | ||
| 3879 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 511 times.
|
511 | true := subtype(t1,t2); |
| 3880 | 511 | (e_1,t2) := matchType(e,t1,t2,printFailtrace); | |
| 3881 | then (e_1,t2); | ||
| 3882 | |||
| 3883 | case (e, DAE.T_METABOXED(ty = t1), t2 as DAE.T_INTEGER()) | ||
| 3884 | algorithm | ||
| 3885 |
2/2✓ Branch 1 taken 15 times.
✓ Branch 2 taken 162 times.
|
177 | true := subtype(t1,t2); |
| 3886 | 162 | matchType(e,t1,t2,printFailtrace); | |
| 3887 | 162 | t := simplifyType(t2); | |
| 3888 | 162 | then (DAE.UNBOX(e,t),t2); | |
| 3889 | |||
| 3890 | case (e, DAE.T_METABOXED(ty = t1), t2 as DAE.T_REAL()) | ||
| 3891 | algorithm | ||
| 3892 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
|
68 | true := subtype(t1,t2); |
| 3893 | 68 | matchType(e,t1,t2,printFailtrace); | |
| 3894 | 68 | t := simplifyType(t2); | |
| 3895 | 68 | then (DAE.UNBOX(e,t),t2); | |
| 3896 | |||
| 3897 | case (e, DAE.T_METABOXED(ty = t1), t2 as DAE.T_BOOL()) | ||
| 3898 | algorithm | ||
| 3899 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 74 times.
|
74 | true := subtype(t1,t2); |
| 3900 | 74 | matchType(e,t1,t2,printFailtrace); | |
| 3901 | 74 | t := simplifyType(t2); | |
| 3902 | 74 | then (DAE.UNBOX(e,t),t2); | |
| 3903 | |||
| 3904 | case (e, DAE.T_METABOXED(ty = t1), t2 as DAE.T_ENUMERATION()) | ||
| 3905 | algorithm | ||
| 3906 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | true := subtype(t1, t2); |
| 3907 | ✗ | matchType(e, t1, t2, printFailtrace); | |
| 3908 | ✗ | t := simplifyType(t2); | |
| 3909 | ✗ | then | |
| 3910 | (DAE.UNBOX(e, t), t2); | ||
| 3911 | |||
| 3912 | case (e, DAE.T_METABOXED(ty = t1), t2 as DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(_))) | ||
| 3913 | algorithm | ||
| 3914 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | true := subtype(t1,t2); |
| 3915 | 2 | (e_1,_) := matchType(e,t1,t2,printFailtrace); | |
| 3916 | 2 | t := simplifyType(t2); | |
| 3917 | 2 | then | |
| 3918 | (DAE.CALL(Absyn.IDENT("mmc_unbox_record"),{e_1},DAE.CALL_ATTR(t,false,true,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS)),t2); | ||
| 3919 | |||
| 3920 | end matchcontinue; | ||
| 3921 | end typeConvert; | ||
| 3922 | |||
| 3923 | protected function liftExpType "help function to typeConvert. Changes the DAE.Type stored | ||
| 3924 | in expression (which is typically a CAST) by adding a dimension to it, making it into an array | ||
| 3925 | type." | ||
| 3926 | input DAE.Exp ie; | ||
| 3927 | input DAE.Dimension dim; | ||
| 3928 | output DAE.Exp res; | ||
| 3929 | algorithm | ||
| 3930 | res := match ie | ||
| 3931 | local DAE.Type ty,ty1; DAE.Exp e; | ||
| 3932 | case DAE.CAST(ty,e) | ||
| 3933 | algorithm | ||
| 3934 | 339 | ty1 := Expression.liftArrayR(ty,dim); | |
| 3935 | 339 | then DAE.CAST(ty1,e); | |
| 3936 | |||
| 3937 | case e then e; | ||
| 3938 | end match; | ||
| 3939 | end liftExpType; | ||
| 3940 | |||
| 3941 | public function typeConvertArray | ||
| 3942 | "Calls typeConvert on a list of expressions." | ||
| 3943 | input list<DAE.Exp> inArray; | ||
| 3944 | input DAE.Type inActualType; | ||
| 3945 | input DAE.Type inExpectedType; | ||
| 3946 | input Boolean inPrintFailtrace; | ||
| 3947 | output list<DAE.Exp> outArray; | ||
| 3948 | algorithm | ||
| 3949 | outArray := match inArray | ||
| 3950 | local | ||
| 3951 | DAE.Exp e; | ||
| 3952 | list<DAE.Exp> expl; | ||
| 3953 | |||
| 3954 | // Empty array. Create a dummy expression and try to type convert that, to | ||
| 3955 | // make sure that empty arrays are type checked. | ||
| 3956 | case {} | ||
| 3957 | algorithm | ||
| 3958 | 3496 | e := makeDummyExpFromType(inActualType); | |
| 3959 | 3496 | typeConvert(e, inActualType, inExpectedType, inPrintFailtrace); | |
| 3960 | then | ||
| 3961 | {}; | ||
| 3962 | |||
| 3963 | else | ||
| 3964 | algorithm | ||
| 3965 |
2/2✓ Branch 0 taken 70852 times.
✓ Branch 1 taken 5334 times.
|
147038 | expl := List.map_2(inArray, function typeConvert(actual = inActualType, expected = inExpectedType, printFailtrace = inPrintFailtrace)); |
| 3966 | then | ||
| 3967 | expl; | ||
| 3968 | |||
| 3969 | end match; | ||
| 3970 | end typeConvertArray; | ||
| 3971 | |||
| 3972 | protected function typeConvertMatrix " | ||
| 3973 | Helper function to type_convert. Handles matrix expressions. | ||
| 3974 | " | ||
| 3975 | input list<list<DAE.Exp>> inMatrix; | ||
| 3976 | input DAE.Type inActualType; | ||
| 3977 | input DAE.Type inExpectedType; | ||
| 3978 | input Boolean printFailtrace; | ||
| 3979 | output list<list<DAE.Exp>> outMatrix; | ||
| 3980 | algorithm | ||
| 3981 |
2/2✓ Branch 0 taken 105 times.
✓ Branch 1 taken 30 times.
|
240 | outMatrix := List.map3(inMatrix, typeConvertArray, inActualType, |
| 3982 | inExpectedType, printFailtrace); | ||
| 3983 | end typeConvertMatrix; | ||
| 3984 | |||
| 3985 | protected function typeConvertList " | ||
| 3986 | Helper function to type_convert. | ||
| 3987 | " | ||
| 3988 | input list<DAE.Exp> inExpExpLst1; | ||
| 3989 | input list<DAE.Type> inTypeLst2; | ||
| 3990 | input list<DAE.Type> inTypeLst3; | ||
| 3991 | input Boolean printFailtrace; | ||
| 3992 | output list<DAE.Exp> outExpExpLst; | ||
| 3993 | output list<DAE.Type> outTypeLst; | ||
| 3994 | algorithm | ||
| 3995 | (outExpExpLst,outTypeLst):= | ||
| 3996 | match (inExpExpLst1, inTypeLst2, inTypeLst3) | ||
| 3997 | local | ||
| 3998 | list<DAE.Exp> rest_1,rest; | ||
| 3999 | list<DAE.Type> tyrest_1,ty1rest,ty2rest; | ||
| 4000 | DAE.Exp first_1,first; | ||
| 4001 | Type ty_1,ty1,ty2; | ||
| 4002 | case ({}, _, _) then ({},{}); | ||
| 4003 | case ((first :: rest), (ty1 :: ty1rest), (ty2 :: ty2rest)) | ||
| 4004 | algorithm | ||
| 4005 | ✗ | (rest_1,tyrest_1) := typeConvertList(rest, ty1rest, ty2rest,printFailtrace); | |
| 4006 | ✗ | (first_1,ty_1) := typeConvert(first, ty1, ty2, printFailtrace); | |
| 4007 | ✗ | then | |
| 4008 | ((first_1 :: rest_1),(ty_1 :: tyrest_1)); | ||
| 4009 | end match; | ||
| 4010 | end typeConvertList; | ||
| 4011 | |||
| 4012 | protected function typeConvertMatrixToList | ||
| 4013 | input list<list<DAE.Exp>> melist; | ||
| 4014 | input DAE.Type inType; | ||
| 4015 | input DAE.Type outType; | ||
| 4016 | input Boolean printFailtrace; | ||
| 4017 | output list<DAE.Exp> outExp; | ||
| 4018 | output DAE.Type actualOutType; | ||
| 4019 | algorithm | ||
| 4020 | (outExp,actualOutType) := matchcontinue (melist, inType, outType) | ||
| 4021 | local | ||
| 4022 | list<DAE.Exp> expl; | ||
| 4023 | list<list<DAE.Exp>> rest; | ||
| 4024 | Type t1,t2; | ||
| 4025 | DAE.Exp e; | ||
| 4026 | |||
| 4027 | case ({}, _, _) then ({},DAE.T_UNKNOWN_DEFAULT); | ||
| 4028 | case (expl::rest, DAE.T_ARRAY(ty=DAE.T_ARRAY(ty=t1)), DAE.T_METALIST(ty=DAE.T_METALIST(ty=t2))) | ||
| 4029 | algorithm | ||
| 4030 | 24 | (e,t1) := typeConvertMatrixRowToList(expl, t1, t2, printFailtrace); | |
| 4031 | 24 | (expl,_) := typeConvertMatrixToList(rest, inType, outType, printFailtrace); | |
| 4032 | 24 | then (e::expl,DAE.T_METALIST(t1)); | |
| 4033 | else | ||
| 4034 | algorithm | ||
| 4035 | ✗ | true := Flags.isSet(Flags.TYPES); | |
| 4036 | ✗ | Debug.trace("- typeConvertMatrixToList failed\n"); | |
| 4037 | ✗ | then fail(); | |
| 4038 | end matchcontinue; | ||
| 4039 | end typeConvertMatrixToList; | ||
| 4040 | |||
| 4041 | protected function typeConvertMatrixRowToList | ||
| 4042 | input list<DAE.Exp> elist; | ||
| 4043 | input DAE.Type inType; | ||
| 4044 | input DAE.Type outType; | ||
| 4045 | input Boolean printFailtrace; | ||
| 4046 | output DAE.Exp out; | ||
| 4047 | output DAE.Type t1; | ||
| 4048 | protected | ||
| 4049 | list<DAE.Exp> elist_1; | ||
| 4050 | algorithm | ||
| 4051 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
|
24 | (elist_1,t1::_) := matchTypeList(elist, inType, outType, printFailtrace); |
| 4052 | 24 | out := DAE.LIST(elist_1); | |
| 4053 | 24 | t1 := DAE.T_METALIST(t1); | |
| 4054 | end typeConvertMatrixRowToList; | ||
| 4055 | |||
| 4056 | public function matchWithPromote "This function is used for matching expressions in matrix construction, | ||
| 4057 | where automatic promotion is allowed. This means that array dimensions of | ||
| 4058 | size one (1) is added from the right to arrays of matrix construction until | ||
| 4059 | all elements have the same dimension size (with a maximum of 2). | ||
| 4060 | For instance, {1,{2}} becomes {1,2}. | ||
| 4061 | The function also has a flag indicating that Integer to Real | ||
| 4062 | conversion can be used." | ||
| 4063 | input DAE.Properties inProperties1; | ||
| 4064 | input DAE.Properties inProperties2; | ||
| 4065 | input Boolean inBoolean3; | ||
| 4066 | output DAE.Properties outProperties; | ||
| 4067 | algorithm | ||
| 4068 | outProperties := matchcontinue (inProperties1,inProperties2,inBoolean3) | ||
| 4069 | local | ||
| 4070 | Type t,t1,t2; | ||
| 4071 | Const c,c1,c2; | ||
| 4072 | DAE.Dimension dim,dim1; | ||
| 4073 | Boolean havereal; | ||
| 4074 | list<DAE.Var> v; | ||
| 4075 | |||
| 4076 | case (DAE.PROP(DAE.T_SUBTYPE_BASIC(complexType = t1),c1),DAE.PROP(t2,c2),havereal) | ||
| 4077 | ✗ | then matchWithPromote(DAE.PROP(t1,c1),DAE.PROP(t2,c2),havereal); | |
| 4078 | |||
| 4079 | case (DAE.PROP(t1,c1),DAE.PROP(DAE.T_SUBTYPE_BASIC(complexType = t2),c2),havereal) | ||
| 4080 | ✗ | then matchWithPromote(DAE.PROP(t1,c1),DAE.PROP(t2,c2),havereal); | |
| 4081 | |||
| 4082 | case (DAE.PROP(type_ = DAE.T_ARRAY(dims = {dim1},ty = t1),constFlag = c1), | ||
| 4083 | DAE.PROP(type_ = DAE.T_ARRAY(dims = {_},ty = t2),constFlag = c2), | ||
| 4084 | havereal) // Allow Integer => Real | ||
| 4085 | algorithm | ||
| 4086 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 9596 times.
|
9596 | DAE.PROP(t,c) := matchWithPromote(DAE.PROP(t1,c1), DAE.PROP(t2,c2), havereal); |
| 4087 | dim := dim1; | ||
| 4088 | 9596 | then | |
| 4089 | DAE.PROP(DAE.T_ARRAY(t,{dim}),c); | ||
| 4090 | |||
| 4091 | // match integer, second | ||
| 4092 | case (DAE.PROP(type_ = t1,constFlag = c1), | ||
| 4093 | DAE.PROP(type_ = DAE.T_ARRAY(dims = {DAE.DIM_INTEGER(1)},ty = t2),constFlag = c2), | ||
| 4094 | havereal) | ||
| 4095 | algorithm | ||
| 4096 | ✗ | false := isArray(t1); | |
| 4097 | ✗ | DAE.PROP(t,c) := matchWithPromote(DAE.PROP(t1,c1), DAE.PROP(t2,c2), havereal); | |
| 4098 | ✗ | then | |
| 4099 | DAE.PROP(DAE.T_ARRAY(t, {DAE.DIM_INTEGER(1)}),c); | ||
| 4100 | // match enum, second | ||
| 4101 | case (DAE.PROP(type_ = t1,constFlag = c1), | ||
| 4102 | DAE.PROP(type_ = DAE.T_ARRAY(dims = {dim as DAE.DIM_ENUM(size=1)},ty = t2),constFlag = c2), | ||
| 4103 | havereal) | ||
| 4104 | algorithm | ||
| 4105 | ✗ | false := isArray(t1); | |
| 4106 | ✗ | DAE.PROP(t,c) := matchWithPromote(DAE.PROP(t1,c1), DAE.PROP(t2,c2), havereal); | |
| 4107 | ✗ | then | |
| 4108 | DAE.PROP(DAE.T_ARRAY(t,{dim}),c); | ||
| 4109 | // match boolean, second | ||
| 4110 | case (DAE.PROP(type_ = t1,constFlag = c1), | ||
| 4111 | DAE.PROP(type_ = DAE.T_ARRAY(dims = {dim as DAE.DIM_BOOLEAN()},ty = t2),constFlag = c2), | ||
| 4112 | havereal) | ||
| 4113 | algorithm | ||
| 4114 | ✗ | false := isArray(t1); | |
| 4115 | ✗ | DAE.PROP(t,c) := matchWithPromote(DAE.PROP(t1,c1), DAE.PROP(t2,c2), havereal); | |
| 4116 | ✗ | then | |
| 4117 | DAE.PROP(DAE.T_ARRAY(t,{dim}),c); | ||
| 4118 | // match integer, first | ||
| 4119 | case (DAE.PROP(type_ = DAE.T_ARRAY(dims = {DAE.DIM_INTEGER(1)},ty = t1),constFlag = c1), | ||
| 4120 | DAE.PROP(type_ = t2,constFlag = c2),havereal) | ||
| 4121 | algorithm | ||
| 4122 | ✗ | false := isArray(t2); | |
| 4123 | ✗ | DAE.PROP(t,c) := matchWithPromote(DAE.PROP(t1,c1), DAE.PROP(t2,c2), havereal); | |
| 4124 | ✗ | then | |
| 4125 | DAE.PROP(DAE.T_ARRAY(t,{DAE.DIM_INTEGER(1)}),c); | ||
| 4126 | // match enum, first | ||
| 4127 | case (DAE.PROP(type_ = DAE.T_ARRAY(dims = {dim as DAE.DIM_ENUM(size=1)},ty = t1),constFlag = c1), | ||
| 4128 | DAE.PROP(type_ = t2,constFlag = c2),havereal) | ||
| 4129 | algorithm | ||
| 4130 | ✗ | false := isArray(t2); | |
| 4131 | ✗ | DAE.PROP(t,c) := matchWithPromote(DAE.PROP(t1,c1), DAE.PROP(t2,c2), havereal); | |
| 4132 | ✗ | then | |
| 4133 | DAE.PROP(DAE.T_ARRAY(t,{dim}),c); | ||
| 4134 | // match boolean, first | ||
| 4135 | case (DAE.PROP(type_ = DAE.T_ARRAY(dims = {dim as DAE.DIM_BOOLEAN()},ty = t1),constFlag = c1), | ||
| 4136 | DAE.PROP(type_ = t2,constFlag = c2),havereal) | ||
| 4137 | algorithm | ||
| 4138 | ✗ | false := isArray(t2); | |
| 4139 | ✗ | DAE.PROP(t,c) := matchWithPromote(DAE.PROP(t1,c1), DAE.PROP(t2,c2), havereal); | |
| 4140 | ✗ | then | |
| 4141 | DAE.PROP(DAE.T_ARRAY(t,{dim}),c); | ||
| 4142 | // equal types | ||
| 4143 | case (DAE.PROP(type_ = t1,constFlag = c1), | ||
| 4144 | DAE.PROP(type_ = t2,constFlag = c2),false) | ||
| 4145 | algorithm | ||
| 4146 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2486 times.
|
2486 | false := isArray(t1); |
| 4147 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2486 times.
|
2486 | false := isArray(t2); |
| 4148 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2486 times.
|
2486 | true := equivtypes(t1,t2); |
| 4149 | 2486 | c := constAnd(c1, c2); | |
| 4150 | 2486 | then | |
| 4151 | DAE.PROP(t1,c); | ||
| 4152 | // enums | ||
| 4153 | case (DAE.PROP(type_ = t as DAE.T_ENUMERATION(),constFlag = c1), | ||
| 4154 | DAE.PROP(type_ = DAE.T_ENUMERATION(),constFlag = c2), false) | ||
| 4155 | algorithm | ||
| 4156 | ✗ | c := constAnd(c1, c2) "Have enum and both Enum" ; | |
| 4157 | ✗ | then | |
| 4158 | DAE.PROP(t,c); | ||
| 4159 | // reals | ||
| 4160 | case (DAE.PROP(type_ = DAE.T_REAL(varLst = v),constFlag = c1), | ||
| 4161 | DAE.PROP(type_ = DAE.T_REAL(),constFlag = c2),true) | ||
| 4162 | algorithm | ||
| 4163 | 2312 | c := constAnd(c1, c2) "Have real and both Real" ; | |
| 4164 | 2312 | then | |
| 4165 | DAE.PROP(DAE.T_REAL(v),c); | ||
| 4166 | // integer vs. real | ||
| 4167 | case (DAE.PROP(type_ = DAE.T_INTEGER(),constFlag = c1), | ||
| 4168 | DAE.PROP(type_ = DAE.T_REAL(varLst = v),constFlag = c2),true) | ||
| 4169 | algorithm | ||
| 4170 | ✗ | c := constAnd(c1, c2) "Have real and first Integer" ; | |
| 4171 | ✗ | then | |
| 4172 | DAE.PROP(DAE.T_REAL(v),c); | ||
| 4173 | // real vs. integer | ||
| 4174 | case (DAE.PROP(type_ = DAE.T_REAL(varLst = v),constFlag = c1), | ||
| 4175 | DAE.PROP(type_ = DAE.T_INTEGER(),constFlag = c2),true) | ||
| 4176 | algorithm | ||
| 4177 | ✗ | c := constAnd(c1, c2) "Have real and second Integer" ; | |
| 4178 | ✗ | then | |
| 4179 | DAE.PROP(DAE.T_REAL(v),c); | ||
| 4180 | // both integers | ||
| 4181 | case (DAE.PROP(type_ = DAE.T_INTEGER(),constFlag = c1), | ||
| 4182 | DAE.PROP(type_ = DAE.T_INTEGER(),constFlag = c2),true) | ||
| 4183 | algorithm | ||
| 4184 | ✗ | c := constAnd(c1, c2) "Have real and both Integer" ; | |
| 4185 | ✗ | then | |
| 4186 | DAE.PROP(DAE.T_REAL_DEFAULT,c); | ||
| 4187 | |||
| 4188 | else | ||
| 4189 | algorithm | ||
| 4190 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 4191 | ✗ | Debug.traceln("- Types.matchWithPromote failed on: " + | |
| 4192 | "\nprop1: " + printPropStr(inProperties1) + | ||
| 4193 | "\nprop2: " + printPropStr(inProperties2) + | ||
| 4194 | "\nhaveReal: " + boolString(inBoolean3)); | ||
| 4195 | ✗ | then fail(); | |
| 4196 | end matchcontinue; | ||
| 4197 | end matchWithPromote; | ||
| 4198 | |||
| 4199 | public function constAnd "Returns the *and* operator of two Consts. | ||
| 4200 | I.e. C_CONST iff. both are C_CONST, | ||
| 4201 | C_PARAM iff both are C_PARAM (or one of them C_CONST), | ||
| 4202 | V_VAR otherwise." | ||
| 4203 | input DAE.Const inConst1; | ||
| 4204 | input DAE.Const inConst2; | ||
| 4205 | output DAE.Const outConst; | ||
| 4206 | algorithm | ||
| 4207 | outConst := match(inConst1,inConst2) | ||
| 4208 | case (DAE.C_CONST(),DAE.C_CONST()) then DAE.C_CONST(); | ||
| 4209 | case (DAE.C_CONST(),DAE.C_PARAM()) then DAE.C_PARAM(); | ||
| 4210 | case (DAE.C_PARAM(),DAE.C_CONST()) then DAE.C_PARAM(); | ||
| 4211 | case (DAE.C_PARAM(),DAE.C_PARAM()) then DAE.C_PARAM(); | ||
| 4212 | case (DAE.C_UNKNOWN(), _) then DAE.C_UNKNOWN(); | ||
| 4213 | case (_, DAE.C_UNKNOWN()) then DAE.C_UNKNOWN(); | ||
| 4214 | else DAE.C_VAR(); | ||
| 4215 | end match; | ||
| 4216 | end constAnd; | ||
| 4217 | |||
| 4218 | protected function constTupleAnd "Returns the *and* operator of two TupleConsts | ||
| 4219 | For now, returns first tuple." | ||
| 4220 | input DAE.TupleConst inTupleConst1; | ||
| 4221 | input DAE.TupleConst inTupleConst2; | ||
| 4222 | output DAE.TupleConst outTupleConst; | ||
| 4223 | algorithm | ||
| 4224 | outTupleConst := match inTupleConst1 | ||
| 4225 | local TupleConst c1; | ||
| 4226 | case c1 then c1; | ||
| 4227 | end match; | ||
| 4228 | end constTupleAnd; | ||
| 4229 | |||
| 4230 | public function constOr "Returns the *or* operator of two Const's. | ||
| 4231 | I.e. C_CONST if some is C_CONST, | ||
| 4232 | C_PARAM if none is C_CONST but some is C_PARAM and | ||
| 4233 | V_VAR otherwise." | ||
| 4234 | input DAE.Const inConst1; | ||
| 4235 | input DAE.Const inConst2; | ||
| 4236 | output DAE.Const outConst; | ||
| 4237 | algorithm | ||
| 4238 | outConst := match (inConst1,inConst2) | ||
| 4239 | case (DAE.C_CONST(),_) then DAE.C_CONST(); | ||
| 4240 | case (_,DAE.C_CONST()) then DAE.C_CONST(); | ||
| 4241 | case (DAE.C_PARAM(),_) then DAE.C_PARAM(); | ||
| 4242 | case (_,DAE.C_PARAM()) then DAE.C_PARAM(); | ||
| 4243 | case (DAE.C_UNKNOWN(),_) then DAE.C_UNKNOWN(); | ||
| 4244 | case (_, DAE.C_UNKNOWN()) then DAE.C_UNKNOWN(); | ||
| 4245 | else DAE.C_VAR(); | ||
| 4246 | end match; | ||
| 4247 | end constOr; | ||
| 4248 | |||
| 4249 | public function boolConst "author: PA | ||
| 4250 | Creates a Const value from a bool. | ||
| 4251 | if true, C_CONST, | ||
| 4252 | if false C_VAR | ||
| 4253 | There is no way to create a C_PARAM using this function." | ||
| 4254 | input Boolean inBoolean; | ||
| 4255 | output DAE.Const outConst; | ||
| 4256 | algorithm | ||
| 4257 | ✗ | outConst := match inBoolean | |
| 4258 | case false then DAE.C_VAR(); | ||
| 4259 | case true then DAE.C_CONST(); | ||
| 4260 | end match; | ||
| 4261 | end boolConst; | ||
| 4262 | |||
| 4263 | public function boolConstSize "author: alleb | ||
| 4264 | A version of boolConst supposed to be used by Static.elabBuiltinSize. | ||
| 4265 | Creates a Const value from a bool. If true, C_CONST, if false C_PARAM." | ||
| 4266 | input Boolean inBoolean; | ||
| 4267 | output DAE.Const outConst; | ||
| 4268 | algorithm | ||
| 4269 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | outConst := match inBoolean |
| 4270 | case false then DAE.C_PARAM(); | ||
| 4271 | case true then DAE.C_CONST(); | ||
| 4272 | end match; | ||
| 4273 | end boolConstSize; | ||
| 4274 | |||
| 4275 | public function constEqualOrHigher | ||
| 4276 | input DAE.Const c1; | ||
| 4277 | input DAE.Const c2; | ||
| 4278 | output Boolean b; | ||
| 4279 | algorithm | ||
| 4280 | b := match (c1, c2) | ||
| 4281 | case (DAE.C_CONST(), _) then true; | ||
| 4282 | case (_, DAE.C_CONST()) then false; | ||
| 4283 | case (DAE.C_PARAM(), _) then true; | ||
| 4284 | case (_, DAE.C_PARAM()) then false; | ||
| 4285 | else true; | ||
| 4286 | end match; | ||
| 4287 | end constEqualOrHigher; | ||
| 4288 | |||
| 4289 | public function constEqual | ||
| 4290 | input DAE.Const c1; | ||
| 4291 | input DAE.Const c2; | ||
| 4292 | output Boolean b; | ||
| 4293 | algorithm | ||
| 4294 | 2153477 | b := valueEq(c1,c2); | |
| 4295 | end constEqual; | ||
| 4296 | |||
| 4297 | public function constIsVariable | ||
| 4298 | "Returns true if Const is C_VAR." | ||
| 4299 | input DAE.Const c; | ||
| 4300 | output Boolean b; | ||
| 4301 | algorithm | ||
| 4302 | 1079270 | b := constEqual(c, DAE.C_VAR()); | |
| 4303 | end constIsVariable; | ||
| 4304 | |||
| 4305 | public function constIsParameter | ||
| 4306 | "Returns true if Const is C_PARAM." | ||
| 4307 | input DAE.Const c; | ||
| 4308 | output Boolean b; | ||
| 4309 | algorithm | ||
| 4310 | ✗ | b := constEqual(c, DAE.C_PARAM()); | |
| 4311 | end constIsParameter; | ||
| 4312 | |||
| 4313 | public function constIsConst | ||
| 4314 | "Returns true if Const is C_CONST." | ||
| 4315 | input DAE.Const c; | ||
| 4316 | output Boolean b; | ||
| 4317 | algorithm | ||
| 4318 | 1074207 | b := constEqual(c, DAE.C_CONST()); | |
| 4319 | end constIsConst; | ||
| 4320 | |||
| 4321 | public function printPropStr "Print the properties to a string." | ||
| 4322 | input DAE.Properties inProperties; | ||
| 4323 | output String outString; | ||
| 4324 | algorithm | ||
| 4325 | outString := match inProperties | ||
| 4326 | local | ||
| 4327 | String ty_str,const_str,res; | ||
| 4328 | DAE.Type ty; | ||
| 4329 | DAE.Const const; | ||
| 4330 | DAE.TupleConst tconst; | ||
| 4331 | case DAE.PROP(type_ = ty,constFlag = const) | ||
| 4332 | algorithm | ||
| 4333 | ✗ | ty_str := TypesDump.unparseType(ty); | |
| 4334 | ✗ | const_str := TypesDump.printConstStr(const); | |
| 4335 | ✗ | res := stringAppendList({"DAE.PROP(",ty_str,", ",const_str,")"}); | |
| 4336 | then | ||
| 4337 | res; | ||
| 4338 | case DAE.PROP_TUPLE(type_ = ty,tupleConst = tconst) | ||
| 4339 | algorithm | ||
| 4340 | ✗ | ty_str := TypesDump.unparseType(ty); | |
| 4341 | ✗ | const_str := TypesDump.printTupleConstStr(tconst); | |
| 4342 | ✗ | res := stringAppendList({"DAE.PROP_TUPLE(",ty_str,", ",const_str,")"}); | |
| 4343 | then | ||
| 4344 | res; | ||
| 4345 | end match; | ||
| 4346 | end printPropStr; | ||
| 4347 | |||
| 4348 | public function printProp "Print the Properties to the Print buffer." | ||
| 4349 | input DAE.Properties p; | ||
| 4350 | protected | ||
| 4351 | String str; | ||
| 4352 | algorithm | ||
| 4353 | ✗ | str := printPropStr(p); | |
| 4354 | ✗ | Print.printErrorBuf(str); | |
| 4355 | end printProp; | ||
| 4356 | |||
| 4357 | public function flowVariables "This function retrieves all variables names that are flow variables, and | ||
| 4358 | prepends the prefix given as an DAE.ComponentRef" | ||
| 4359 | input list<DAE.Var> inVarLst; | ||
| 4360 | input DAE.ComponentRef inComponentRef; | ||
| 4361 | output list<DAE.ComponentRef> outExpComponentRefLst; | ||
| 4362 | algorithm | ||
| 4363 | outExpComponentRefLst:= | ||
| 4364 | matchcontinue (inVarLst,inComponentRef) | ||
| 4365 | local | ||
| 4366 | DAE.ComponentRef cr_1,cr; | ||
| 4367 | list<DAE.ComponentRef> res; | ||
| 4368 | String id; | ||
| 4369 | list<DAE.Var> vs; | ||
| 4370 | DAE.Type ty2,ty; | ||
| 4371 | |||
| 4372 | // handle empty case | ||
| 4373 | case ({},_) then {}; | ||
| 4374 | |||
| 4375 | // we have a flow prefix | ||
| 4376 | case ((DAE.TYPES_VAR(name = id,attributes = DAE.ATTR(connectorType = DAE.FLOW()),ty = ty) :: vs),cr) | ||
| 4377 | algorithm | ||
| 4378 | ✗ | ty2 := simplifyType(ty); | |
| 4379 | ✗ | cr_1 := ComponentReference.crefPrependIdent(cr, id,{},ty2); | |
| 4380 | // print("\n created: " + ComponentReference.debugPrintComponentRefTypeStr(cr_1) + "\n"); | ||
| 4381 | ✗ | res := flowVariables(vs, cr); | |
| 4382 | then | ||
| 4383 | (cr_1 :: res); | ||
| 4384 | |||
| 4385 | // handle the rest | ||
| 4386 | case ((_ :: vs),cr) | ||
| 4387 | algorithm | ||
| 4388 | ✗ | res := flowVariables(vs, cr); | |
| 4389 | then | ||
| 4390 | res; | ||
| 4391 | end matchcontinue; | ||
| 4392 | end flowVariables; | ||
| 4393 | |||
| 4394 | public function streamVariables "This function retrieves all variables names that are stream variables, | ||
| 4395 | and prepends the prefix given as an DAE.ComponentRef" | ||
| 4396 | input list<DAE.Var> inVarLst; | ||
| 4397 | input DAE.ComponentRef inComponentRef; | ||
| 4398 | output list<DAE.ComponentRef> outExpComponentRefLst; | ||
| 4399 | algorithm | ||
| 4400 | outExpComponentRefLst:= | ||
| 4401 | matchcontinue (inVarLst,inComponentRef) | ||
| 4402 | local | ||
| 4403 | DAE.ComponentRef cr_1,cr; | ||
| 4404 | list<DAE.ComponentRef> res; | ||
| 4405 | String id; | ||
| 4406 | list<DAE.Var> vs; | ||
| 4407 | DAE.Type ty2,ty; | ||
| 4408 | |||
| 4409 | case ({},_) then {}; | ||
| 4410 | case ((DAE.TYPES_VAR(name = id,attributes = DAE.ATTR(connectorType = DAE.STREAM()),ty = ty) :: vs),cr) | ||
| 4411 | algorithm | ||
| 4412 | ✗ | ty2 := simplifyType(ty); | |
| 4413 | ✗ | cr_1 := ComponentReference.crefPrependIdent(cr, id, {}, ty2); | |
| 4414 | ✗ | res := streamVariables(vs, cr); | |
| 4415 | then | ||
| 4416 | (cr_1 :: res); | ||
| 4417 | case ((_ :: vs),cr) | ||
| 4418 | algorithm | ||
| 4419 | ✗ | res := streamVariables(vs, cr); | |
| 4420 | then | ||
| 4421 | res; | ||
| 4422 | end matchcontinue; | ||
| 4423 | end streamVariables; | ||
| 4424 | |||
| 4425 | public function getAllExps "This function goes through the Type structure and finds all the | ||
| 4426 | expressions and returns them in a list" | ||
| 4427 | input DAE.Type inType; | ||
| 4428 | output list<DAE.Exp> outExpExpLst; | ||
| 4429 | algorithm | ||
| 4430 | ✗ | outExpExpLst := getAllExpsTt(inType); | |
| 4431 | end getAllExps; | ||
| 4432 | |||
| 4433 | protected function getAllExpsTt "This function goes through the TType structure and finds all the | ||
| 4434 | expressions and returns them in a list" | ||
| 4435 | input DAE.Type inType; | ||
| 4436 | output list<DAE.Exp> outExpExpLst; | ||
| 4437 | algorithm | ||
| 4438 | outExpExpLst := matchcontinue inType | ||
| 4439 | local | ||
| 4440 | list<DAE.Exp> exps,tyexps; | ||
| 4441 | list<DAE.Var> vars, attrs; | ||
| 4442 | Type ty; | ||
| 4443 | list<DAE.Type> tys; | ||
| 4444 | list<list<DAE.Exp>> explists,explist; | ||
| 4445 | list<DAE.FuncArg> fargs; | ||
| 4446 | Type tty; | ||
| 4447 | String str; | ||
| 4448 | |||
| 4449 | ✗ | case DAE.T_INTEGER(varLst = vars) then getAllExpsVars(vars); | |
| 4450 | ✗ | case DAE.T_REAL(varLst = vars) then getAllExpsVars(vars); | |
| 4451 | ✗ | case DAE.T_STRING(varLst = vars) then getAllExpsVars(vars); | |
| 4452 | ✗ | case DAE.T_BOOL(varLst = vars) then getAllExpsVars(vars); | |
| 4453 | // BTH return empty list for clock since it doesn't have attributes | ||
| 4454 | case DAE.T_CLOCK() then {}; | ||
| 4455 | case DAE.T_ENUMERATION(literalVarLst = vars, attributeLst = attrs) | ||
| 4456 | algorithm | ||
| 4457 | ✗ | exps := getAllExpsVars(vars); | |
| 4458 | ✗ | tyexps := getAllExpsVars(attrs); | |
| 4459 | ✗ | exps := listAppend(tyexps, exps); | |
| 4460 | then | ||
| 4461 | exps; | ||
| 4462 | ✗ | case DAE.T_ARRAY(ty = ty) then getAllExps(ty); | |
| 4463 | |||
| 4464 | ✗ | case DAE.T_COMPLEX(varLst = vars) then getAllExpsVars(vars); | |
| 4465 | ✗ | case DAE.T_SUBTYPE_BASIC(varLst = vars) then getAllExpsVars(vars); | |
| 4466 | |||
| 4467 | case DAE.T_FUNCTION(funcArg = fargs,funcResultType = ty) | ||
| 4468 | algorithm | ||
| 4469 | ✗ | explists := List.mapMap(fargs, funcArgType, getAllExps); | |
| 4470 | ✗ | tyexps := getAllExps(ty); | |
| 4471 | ✗ | exps := List.flatten((tyexps :: explists)); | |
| 4472 | then | ||
| 4473 | exps; | ||
| 4474 | |||
| 4475 | case DAE.T_TUPLE(types = tys) | ||
| 4476 | algorithm | ||
| 4477 | ✗ | explist := List.map(tys, getAllExps); | |
| 4478 | ✗ | exps := List.flatten(explist); | |
| 4479 | then | ||
| 4480 | exps; | ||
| 4481 | |||
| 4482 | case DAE.T_METATUPLE(types = tys) | ||
| 4483 | algorithm | ||
| 4484 | ✗ | exps := getAllExpsTt(DAE.T_TUPLE(tys, NONE())); | |
| 4485 | then | ||
| 4486 | exps; | ||
| 4487 | |||
| 4488 | case DAE.T_METAUNIONTYPE() then {}; | ||
| 4489 | |||
| 4490 | ✗ | case DAE.T_METAOPTION(ty = ty) then getAllExps(ty); | |
| 4491 | ✗ | case DAE.T_METALIST(ty = ty) then getAllExps(ty); | |
| 4492 | ✗ | case DAE.T_METAARRAY(ty = ty) then getAllExps(ty); | |
| 4493 | ✗ | case DAE.T_METABOXED(ty = ty) then getAllExps(ty); | |
| 4494 | case DAE.T_METAPOLYMORPHIC() then {}; | ||
| 4495 | |||
| 4496 | case DAE.T_UNKNOWN() then {}; | ||
| 4497 | case DAE.T_NORETCALL() then {}; | ||
| 4498 | |||
| 4499 | case tty | ||
| 4500 | algorithm | ||
| 4501 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 4502 | ✗ | str := TypesDump.unparseType(tty); | |
| 4503 | ✗ | Debug.traceln("-- Types.getAllExpsTt failed " + str); | |
| 4504 | ✗ | then | |
| 4505 | fail(); | ||
| 4506 | end matchcontinue; | ||
| 4507 | end getAllExpsTt; | ||
| 4508 | |||
| 4509 | protected function getAllExpsVars "Helper function to getAllExpsTt." | ||
| 4510 | input list<DAE.Var> vars; | ||
| 4511 | output list<DAE.Exp> exps; | ||
| 4512 | protected | ||
| 4513 | list<list<DAE.Exp>> explist; | ||
| 4514 | algorithm | ||
| 4515 | ✗ | explist := List.map(vars, getAllExpsVar); | |
| 4516 | ✗ | exps := List.flatten(explist); | |
| 4517 | end getAllExpsVars; | ||
| 4518 | |||
| 4519 | protected function getAllExpsVar "Helper function to getAllExpsVars." | ||
| 4520 | input DAE.Var inVar; | ||
| 4521 | output list<DAE.Exp> outExpExpLst; | ||
| 4522 | algorithm | ||
| 4523 | outExpExpLst := match inVar | ||
| 4524 | local | ||
| 4525 | list<DAE.Exp> tyexps,bndexp,exps; | ||
| 4526 | DAE.Type ty; | ||
| 4527 | DAE.Binding bnd; | ||
| 4528 | |||
| 4529 | case DAE.TYPES_VAR(ty = ty,binding = bnd) | ||
| 4530 | algorithm | ||
| 4531 | ✗ | tyexps := getAllExps(ty); | |
| 4532 | ✗ | bndexp := getAllExpsBinding(bnd); | |
| 4533 | ✗ | exps := listAppend(tyexps, bndexp); | |
| 4534 | then | ||
| 4535 | exps; | ||
| 4536 | end match; | ||
| 4537 | end getAllExpsVar; | ||
| 4538 | |||
| 4539 | protected function getAllExpsBinding "Helper function to get_all_exps_var." | ||
| 4540 | input DAE.Binding inBinding; | ||
| 4541 | output list<DAE.Exp> outExpExpLst; | ||
| 4542 | algorithm | ||
| 4543 | outExpExpLst := match inBinding | ||
| 4544 | local | ||
| 4545 | DAE.Exp exp; | ||
| 4546 | case DAE.EQBOUND(exp = exp) then {exp}; | ||
| 4547 | case DAE.UNBOUND() then {}; | ||
| 4548 | case DAE.VALBOUND() then {}; | ||
| 4549 | else | ||
| 4550 | algorithm | ||
| 4551 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 4552 | ✗ | Debug.trace("-- Types.getAllExpsBinding failed\n"); | |
| 4553 | ✗ | then | |
| 4554 | fail(); | ||
| 4555 | end match; | ||
| 4556 | end getAllExpsBinding; | ||
| 4557 | |||
| 4558 | public function isBoxedType | ||
| 4559 | input DAE.Type ty; | ||
| 4560 | output Boolean b; | ||
| 4561 | algorithm | ||
| 4562 | b := match ty | ||
| 4563 | case DAE.T_STRING() then true; | ||
| 4564 | case DAE.T_METAOPTION() then true; | ||
| 4565 | case DAE.T_METALIST() then true; | ||
| 4566 | case DAE.T_METATUPLE() then true; | ||
| 4567 | case DAE.T_METAUNIONTYPE() then true; | ||
| 4568 | case DAE.T_METARECORD() then true; | ||
| 4569 | case DAE.T_METAPOLYMORPHIC() then true; | ||
| 4570 | case DAE.T_METAARRAY() then true; | ||
| 4571 | case DAE.T_FUNCTION() then true; | ||
| 4572 | case DAE.T_METABOXED() then true; | ||
| 4573 | case DAE.T_ANYTYPE() then true; | ||
| 4574 | case DAE.T_UNKNOWN() then true; | ||
| 4575 | case DAE.T_METATYPE() then true; | ||
| 4576 | case DAE.T_NORETCALL() then true; | ||
| 4577 | case DAE.T_CODE() then true; | ||
| 4578 | case DAE.T_COMPLEX(complexClassType = ClassInf.EXTERNAL_OBJ()) then true; | ||
| 4579 | else false; | ||
| 4580 | end match; | ||
| 4581 | end isBoxedType; | ||
| 4582 | |||
| 4583 | public function isMetaBoxedType | ||
| 4584 | input DAE.Type inType; | ||
| 4585 | output Boolean outIsMetaBoxed; | ||
| 4586 | algorithm | ||
| 4587 | outIsMetaBoxed := match inType | ||
| 4588 | case DAE.T_METABOXED() then true; | ||
| 4589 | else false; | ||
| 4590 | end match; | ||
| 4591 | end isMetaBoxedType; | ||
| 4592 | |||
| 4593 | public function boxIfUnboxedType | ||
| 4594 | input DAE.Type ty; | ||
| 4595 | output DAE.Type outType; | ||
| 4596 | algorithm | ||
| 4597 | outType := matchcontinue ty | ||
| 4598 | local | ||
| 4599 | list<DAE.Type> tys; | ||
| 4600 | |||
| 4601 | case DAE.T_TUPLE() | ||
| 4602 | algorithm | ||
| 4603 | 699 | tys := List.map(ty.types, boxIfUnboxedType); | |
| 4604 | 699 | then DAE.T_METATUPLE(tys); // TODO?! should now propagate the type source? | |
| 4605 | |||
| 4606 |
2/2✓ Branch 1 taken 50227 times.
✓ Branch 2 taken 395433 times.
|
445660 | else if isBoxedType(ty) then ty else DAE.T_METABOXED(ty); |
| 4607 | |||
| 4608 | end matchcontinue; | ||
| 4609 | end boxIfUnboxedType; | ||
| 4610 | |||
| 4611 | public function unboxedType | ||
| 4612 | input DAE.Type ity; | ||
| 4613 | output DAE.Type out; | ||
| 4614 | algorithm | ||
| 4615 | out := match ity | ||
| 4616 | local | ||
| 4617 | list<DAE.Type> tys; | ||
| 4618 | Type t, ty; | ||
| 4619 | |||
| 4620 | 5932 | case DAE.T_METABOXED() then unboxedType(ity.ty); | |
| 4621 | |||
| 4622 | case DAE.T_METAOPTION() | ||
| 4623 | algorithm | ||
| 4624 | 641 | ty := unboxedType(ity.ty); | |
| 4625 | 641 | ty := boxIfUnboxedType(ty); | |
| 4626 | 641 | then DAE.T_METAOPTION(ty); | |
| 4627 | |||
| 4628 | case DAE.T_METALIST() | ||
| 4629 | algorithm | ||
| 4630 | 2923 | ty := unboxedType(ity.ty); | |
| 4631 | 2923 | ty := boxIfUnboxedType(ty); | |
| 4632 | 2923 | then | |
| 4633 | DAE.T_METALIST(ty); | ||
| 4634 | |||
| 4635 | case DAE.T_METATUPLE() | ||
| 4636 | algorithm | ||
| 4637 | 2672 | tys := List.mapMap(ity.types, unboxedType, boxIfUnboxedType); | |
| 4638 | 2672 | then | |
| 4639 | DAE.T_METATUPLE(tys); | ||
| 4640 | |||
| 4641 | case DAE.T_METAARRAY() | ||
| 4642 | algorithm | ||
| 4643 | 81 | ty := unboxedType(ity.ty); | |
| 4644 | 81 | ty := boxIfUnboxedType(ty); | |
| 4645 | 81 | then DAE.T_METAARRAY(ty); | |
| 4646 | |||
| 4647 | case t as DAE.T_ARRAY() | ||
| 4648 | algorithm | ||
| 4649 | 790 | t.ty := unboxedType(t.ty); | |
| 4650 | then t; | ||
| 4651 | |||
| 4652 | else ity; | ||
| 4653 | end match; | ||
| 4654 | end unboxedType; | ||
| 4655 | |||
| 4656 | public function listMatchSuperType "Takes lists of Exp,Type and calculates the | ||
| 4657 | supertype of the list, then converts the expressions to this type. | ||
| 4658 | " | ||
| 4659 | input list<DAE.Exp> ielist; | ||
| 4660 | input list<DAE.Type> typeList; | ||
| 4661 | input Boolean printFailtrace; | ||
| 4662 | output list<DAE.Exp> out; | ||
| 4663 | output DAE.Type t; | ||
| 4664 | algorithm | ||
| 4665 | (out,t) := matchcontinue (ielist, typeList) | ||
| 4666 | local | ||
| 4667 | Type st; | ||
| 4668 | list<DAE.Exp> elist; | ||
| 4669 | |||
| 4670 | case ({}, {}) then ({}, DAE.T_UNKNOWN_DEFAULT); | ||
| 4671 | case (_ :: _, _ :: _) | ||
| 4672 | algorithm | ||
| 4673 | 3441 | st := List.reduce(typeList, superType); | |
| 4674 | 3441 | st := superType(st,st); | |
| 4675 | 3441 | st := unboxedType(st); | |
| 4676 | 3441 | elist := listMatchSuperType2(ielist,typeList,st,printFailtrace); | |
| 4677 | then (elist, st); | ||
| 4678 | else | ||
| 4679 | algorithm | ||
| 4680 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 4681 | ✗ | Debug.trace("- Types.listMatchSuperType failed\n"); | |
| 4682 | ✗ | then fail(); | |
| 4683 | end matchcontinue; | ||
| 4684 | end listMatchSuperType; | ||
| 4685 | |||
| 4686 | protected function listMatchSuperType2 | ||
| 4687 | input list<DAE.Exp> elist; | ||
| 4688 | input list<DAE.Type> typeList; | ||
| 4689 | input DAE.Type st; | ||
| 4690 | input Boolean printFailtrace; | ||
| 4691 | output list<DAE.Exp> out; | ||
| 4692 | algorithm | ||
| 4693 | out := matchcontinue (elist, typeList) | ||
| 4694 | local | ||
| 4695 | DAE.Exp e; | ||
| 4696 | list<DAE.Exp> erest; | ||
| 4697 | Type t; | ||
| 4698 | list<DAE.Type> trest; | ||
| 4699 | String str; | ||
| 4700 | case ({}, {}) then {}; | ||
| 4701 | case (e::erest, t::trest) | ||
| 4702 | algorithm | ||
| 4703 | 20404 | (e,t) := matchType(e,t,st,printFailtrace); | |
| 4704 | 20404 | erest := listMatchSuperType2(erest,trest,st,printFailtrace); | |
| 4705 | then (e::erest); | ||
| 4706 | case (e::_, _) | ||
| 4707 | algorithm | ||
| 4708 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 4709 | ✗ | str := ExpressionBasics.printExpStr(e); | |
| 4710 | ✗ | Debug.traceln("- Types.listMatchSuperType2 failed: " + str); | |
| 4711 | ✗ | then fail(); | |
| 4712 | end matchcontinue; | ||
| 4713 | end listMatchSuperType2; | ||
| 4714 | |||
| 4715 | public function superType "find the supertype of the two types" | ||
| 4716 | input DAE.Type inType1; | ||
| 4717 | input DAE.Type inType2; | ||
| 4718 | output DAE.Type out; | ||
| 4719 | algorithm | ||
| 4720 | out := | ||
| 4721 | matchcontinue (inType1,inType2) | ||
| 4722 | local | ||
| 4723 | Type t1,t2,tp; | ||
| 4724 | list<DAE.Type> type_list1,type_list2; | ||
| 4725 | Absyn.Path path1,path2; | ||
| 4726 | |||
| 4727 | case (DAE.T_ANYTYPE(),t2) then t2; | ||
| 4728 | case (t1,DAE.T_ANYTYPE()) then t1; | ||
| 4729 | case (DAE.T_UNKNOWN(),t2) then t2; | ||
| 4730 | case (t1,DAE.T_UNKNOWN()) then t1; | ||
| 4731 | case (_,t2 as DAE.T_METAPOLYMORPHIC()) then t2; | ||
| 4732 | |||
| 4733 | case (DAE.T_TUPLE(types = type_list1),DAE.T_TUPLE(types = type_list2)) | ||
| 4734 | algorithm | ||
| 4735 | ✗ | type_list1 := List.map(type_list1, boxIfUnboxedType); | |
| 4736 | ✗ | type_list2 := List.map(type_list2, boxIfUnboxedType); | |
| 4737 | ✗ | type_list1 := List.threadMap(type_list1,type_list2,superType); | |
| 4738 | ✗ | then DAE.T_METATUPLE(type_list1); | |
| 4739 | |||
| 4740 | case (DAE.T_TUPLE(types = type_list1),DAE.T_METATUPLE(types = type_list2)) | ||
| 4741 | algorithm | ||
| 4742 | ✗ | type_list1 := List.map(type_list1, boxIfUnboxedType); | |
| 4743 | ✗ | type_list2 := List.map(type_list2, boxIfUnboxedType); | |
| 4744 | ✗ | type_list1 := List.threadMap(type_list1,type_list2,superType); | |
| 4745 | ✗ | then DAE.T_METATUPLE(type_list1); | |
| 4746 | |||
| 4747 | case (DAE.T_METATUPLE(types = type_list1),DAE.T_TUPLE(types = type_list2)) | ||
| 4748 | algorithm | ||
| 4749 | ✗ | type_list1 := List.map(type_list1, boxIfUnboxedType); | |
| 4750 | ✗ | type_list2 := List.map(type_list2, boxIfUnboxedType); | |
| 4751 | ✗ | type_list1 := List.threadMap(type_list1,type_list2,superType); | |
| 4752 | ✗ | then DAE.T_METATUPLE(type_list1); | |
| 4753 | |||
| 4754 | case (DAE.T_METATUPLE(types = type_list1),DAE.T_METATUPLE(types = type_list2)) | ||
| 4755 | algorithm | ||
| 4756 | 19639 | type_list1 := List.map(type_list1, boxIfUnboxedType); | |
| 4757 | 19639 | type_list2 := List.map(type_list2, boxIfUnboxedType); | |
| 4758 | 19639 | type_list1 := List.threadMap(type_list1,type_list2,superType); | |
| 4759 | 19639 | then DAE.T_METATUPLE(type_list1); | |
| 4760 | |||
| 4761 | case (DAE.T_METALIST(ty = t1),DAE.T_METALIST(ty = t2)) | ||
| 4762 | algorithm | ||
| 4763 | 385 | t1 := boxIfUnboxedType(t1); | |
| 4764 | 385 | t2 := boxIfUnboxedType(t2); | |
| 4765 | 385 | tp := superType(t1,t2); | |
| 4766 | 385 | then DAE.T_METALIST(tp); | |
| 4767 | |||
| 4768 | case (DAE.T_METAOPTION(ty = t1), DAE.T_METAOPTION(ty = t2)) | ||
| 4769 | algorithm | ||
| 4770 | 87 | t1 := boxIfUnboxedType(t1); | |
| 4771 | 87 | t2 := boxIfUnboxedType(t2); | |
| 4772 | 87 | tp := superType(t1,t2); | |
| 4773 | 87 | then DAE.T_METAOPTION(tp); | |
| 4774 | |||
| 4775 | case (DAE.T_METAARRAY(ty = t1), DAE.T_METAARRAY(ty = t2)) | ||
| 4776 | algorithm | ||
| 4777 | 1 | t1 := boxIfUnboxedType(t1); | |
| 4778 | 1 | t2 := boxIfUnboxedType(t2); | |
| 4779 | 1 | tp := superType(t1,t2); | |
| 4780 | 1 | then DAE.T_METAARRAY(tp); | |
| 4781 | |||
| 4782 | case (t1 as DAE.T_METAUNIONTYPE(path = path1), DAE.T_METARECORD(utPath=path2)) | ||
| 4783 | algorithm | ||
| 4784 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5342 times.
|
5342 | true := AbsynUtil.pathEqual(path1,path2); |
| 4785 | then t1; | ||
| 4786 | |||
| 4787 | case (DAE.T_METARECORD(knownSingleton=false,utPath = path1), DAE.T_METARECORD(knownSingleton=false,utPath=path2)) | ||
| 4788 | algorithm | ||
| 4789 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 934 times.
|
934 | true := AbsynUtil.pathEqual(path1,path2); |
| 4790 | 934 | then DAE.T_METAUNIONTYPE({},inType1.typeVars,false,DAE.NOT_SINGLETON(),path1); | |
| 4791 | |||
| 4792 | case (DAE.T_INTEGER(),DAE.T_REAL()) | ||
| 4793 | then DAE.T_REAL_DEFAULT; | ||
| 4794 | |||
| 4795 | case (DAE.T_REAL(),DAE.T_INTEGER()) | ||
| 4796 | then DAE.T_REAL_DEFAULT; | ||
| 4797 | |||
| 4798 | case (t1,t2) | ||
| 4799 | algorithm | ||
| 4800 |
2/2✓ Branch 1 taken 62 times.
✓ Branch 2 taken 49804 times.
|
49866 | true := subtype(t1,t2); |
| 4801 | then t2; | ||
| 4802 | |||
| 4803 | case (t1,t2) | ||
| 4804 | algorithm | ||
| 4805 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 62 times.
|
62 | true := subtype(t2,t1); |
| 4806 | then t1; | ||
| 4807 | |||
| 4808 | end matchcontinue; | ||
| 4809 | end superType; | ||
| 4810 | |||
| 4811 | public function matchTypePolymorphic "Like matchType, except we also | ||
| 4812 | bind polymorphic variabled. Used when elaborating calls." | ||
| 4813 | input DAE.Exp iexp; | ||
| 4814 | input DAE.Type iactual; | ||
| 4815 | input DAE.Type expected; | ||
| 4816 | input Option<Absyn.Path> envPath "to detect which polymorphic types are recursive"; | ||
| 4817 | input InstTypes.PolymorphicBindings ipolymorphicBindings; | ||
| 4818 | input Boolean printFailtrace; | ||
| 4819 | output DAE.Exp exp=iexp; | ||
| 4820 | output DAE.Type actual=iactual; | ||
| 4821 | output InstTypes.PolymorphicBindings polymorphicBindings=ipolymorphicBindings; | ||
| 4822 | protected | ||
| 4823 | constant Boolean debug=false; | ||
| 4824 | algorithm | ||
| 4825 |
2/2✓ Branch 1 taken 122680 times.
✓ Branch 2 taken 3366 times.
|
126046 | if /*(if not Config.acceptMetaModelicaGrammar() then true else*/ listEmpty(getAllInnerTypesOfType(expected, isPolymorphic)) then |
| 4826 | 122680 | (exp,actual) := matchType(exp,actual,expected,printFailtrace); | |
| 4827 | else | ||
| 4828 | if debug then print("match type: " + ExpressionBasics.printExpStr(exp) + " of " + TypesDump.unparseType(actual) + " with " + TypesDump.unparseType(expected) + "\n"); end if; | ||
| 4829 | 3366 | (exp,actual) := matchType(exp,actual,DAE.T_METABOXED(DAE.T_UNKNOWN_DEFAULT), printFailtrace); | |
| 4830 | if debug then print("matched type: " + ExpressionBasics.printExpStr(exp) + " of " + TypesDump.unparseType(actual) + " with " + TypesDump.unparseType(expected) + " (boxed)\n"); end if; | ||
| 4831 | 3358 | polymorphicBindings := subtypePolymorphic(getUniontypeIfMetarecordReplaceAllSubtypes(actual), getUniontypeIfMetarecordReplaceAllSubtypes(expected), envPath, polymorphicBindings); | |
| 4832 | if debug then print("match type: " + ExpressionBasics.printExpStr(exp) + " of " + TypesDump.unparseType(actual) + " with " + TypesDump.unparseType(expected) + " and bindings " + polymorphicBindingsStr(polymorphicBindings) + " (OK)\n"); end if; | ||
| 4833 | end if; | ||
| 4834 | end matchTypePolymorphic; | ||
| 4835 | |||
| 4836 | public function matchTypePolymorphicWithError "Like matchType, except we also | ||
| 4837 | bind polymorphic variabled. Used when elaborating calls." | ||
| 4838 | input DAE.Exp iexp; | ||
| 4839 | input DAE.Type iactual; | ||
| 4840 | input DAE.Type iexpected; | ||
| 4841 | input Option<Absyn.Path> envPath "to detect which polymorphic types are recursive"; | ||
| 4842 | input InstTypes.PolymorphicBindings ipolymorphicBindings; | ||
| 4843 | input SourceInfo info; | ||
| 4844 | output DAE.Exp outExp; | ||
| 4845 | output DAE.Type outType; | ||
| 4846 | output InstTypes.PolymorphicBindings outBindings; | ||
| 4847 | algorithm | ||
| 4848 | (outExp,outType,outBindings):= | ||
| 4849 | matchcontinue (iexp, iactual, iexpected, ipolymorphicBindings) | ||
| 4850 | local | ||
| 4851 | DAE.Exp exp; | ||
| 4852 | Type actual,expected; | ||
| 4853 | InstTypes.PolymorphicBindings polymorphicBindings; | ||
| 4854 | String str1,str2,str3; | ||
| 4855 | |||
| 4856 | case (exp, actual, expected, polymorphicBindings) | ||
| 4857 | algorithm | ||
| 4858 | 70 | (exp,actual,polymorphicBindings) := matchTypePolymorphic(exp,actual,expected,envPath,polymorphicBindings,false); | |
| 4859 | then (exp,actual,polymorphicBindings); | ||
| 4860 | else | ||
| 4861 | algorithm | ||
| 4862 | ✗ | str1 := ExpressionBasics.printExpStr(iexp); | |
| 4863 | ✗ | str2 := TypesDump.unparseType(iactual); | |
| 4864 | ✗ | str3 := TypesDump.unparseType(iexpected); | |
| 4865 | ✗ | Error.addSourceMessage(Error.EXP_TYPE_MISMATCH, {str1,str3,str2}, info); | |
| 4866 | ✗ | then fail(); | |
| 4867 | end matchcontinue; | ||
| 4868 | end matchTypePolymorphicWithError; | ||
| 4869 | |||
| 4870 | public function matchType | ||
| 4871 | "This function matches an expression with an expected type, and converts the | ||
| 4872 | expression to the expected type if necessary." | ||
| 4873 | input DAE.Exp inExp; | ||
| 4874 | input DAE.Type inActualType; | ||
| 4875 | input DAE.Type inExpectedType; | ||
| 4876 | input Boolean inPrintFailtrace=false; | ||
| 4877 | output DAE.Exp outExp; | ||
| 4878 | output DAE.Type outType; | ||
| 4879 | algorithm | ||
| 4880 |
2/2✓ Branch 1 taken 2302600 times.
✓ Branch 2 taken 708267 times.
|
3010867 | if subtype(inExpectedType, inActualType) then |
| 4881 | /* TODO: Don't return ANY as type here; use the most restrictive... Else we get issues... */ | ||
| 4882 | outExp := inExp; | ||
| 4883 | 2302600 | outType := inActualType; | |
| 4884 | else | ||
| 4885 | try | ||
| 4886 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 708261 times.
|
708267 | false := subtype(inActualType, inExpectedType); |
| 4887 | 708261 | (outExp, outType) := typeConvert(inExp, inActualType, inExpectedType, inPrintFailtrace); | |
| 4888 | 246457 | outExp := ExpressionSimplify.simplify1(outExp); | |
| 4889 | else | ||
| 4890 | 461810 | printFailure(Flags.TYPES, "matchType", inExp, inActualType, inExpectedType); | |
| 4891 | 461810 | fail(); | |
| 4892 | end try; | ||
| 4893 | end if; | ||
| 4894 | end matchType; | ||
| 4895 | |||
| 4896 | public function matchTypeNoFail | ||
| 4897 | input DAE.Exp inExp; | ||
| 4898 | input DAE.Type inActualType; | ||
| 4899 | input DAE.Type inExpectedType; | ||
| 4900 | output DAE.Exp outExp; | ||
| 4901 | output DAE.Type outType; | ||
| 4902 | output Boolean outMatch; | ||
| 4903 | algorithm | ||
| 4904 |
2/2✓ Branch 1 taken 8293 times.
✓ Branch 2 taken 5 times.
|
8298 | if subtype(inExpectedType, inActualType) then |
| 4905 | outExp := inExp; | ||
| 4906 | 8293 | outType := inActualType; | |
| 4907 | outMatch := true; | ||
| 4908 | else | ||
| 4909 | try | ||
| 4910 | 5 | (outExp, outType) := typeConvert(inExp, inActualType, inExpectedType, false); | |
| 4911 | 5 | outExp := ExpressionSimplify.simplify1(outExp); | |
| 4912 | outMatch := true; | ||
| 4913 | else | ||
| 4914 | outExp := inExp; | ||
| 4915 | ✗ | outType := inActualType; | |
| 4916 | outMatch := true; | ||
| 4917 | end try; | ||
| 4918 | end if; | ||
| 4919 | end matchTypeNoFail; | ||
| 4920 | |||
| 4921 | public function matchTypes | ||
| 4922 | "matchType, list of actual types, one expected type." | ||
| 4923 | input list<DAE.Exp> iexps; | ||
| 4924 | input list<DAE.Type> itys; | ||
| 4925 | input DAE.Type expected; | ||
| 4926 | input Boolean printFailtrace; | ||
| 4927 | output list<DAE.Exp> outExps; | ||
| 4928 | output list<DAE.Type> outTys; | ||
| 4929 | algorithm | ||
| 4930 | 8038 | (outExps, outTys) := matchTypes_tail(iexps, itys, expected, printFailtrace, {}, {}); | |
| 4931 | end matchTypes; | ||
| 4932 | |||
| 4933 | protected function matchTypes_tail | ||
| 4934 | input list<DAE.Exp> iexps; | ||
| 4935 | input list<DAE.Type> itys; | ||
| 4936 | input DAE.Type expected; | ||
| 4937 | input Boolean printFailtrace; | ||
| 4938 | input list<DAE.Exp> inAccumExps; | ||
| 4939 | input list<DAE.Type> inAccumTypes; | ||
| 4940 | output list<DAE.Exp> outExps; | ||
| 4941 | output list<DAE.Type> outTys; | ||
| 4942 | algorithm | ||
| 4943 | (outExps, outTys) := | ||
| 4944 | match(iexps, itys) | ||
| 4945 | local | ||
| 4946 | DAE.Exp e; | ||
| 4947 | list<DAE.Exp> exps; | ||
| 4948 | DAE.Type ty; | ||
| 4949 | list<DAE.Type> tys; | ||
| 4950 | |||
| 4951 | case (e :: exps, ty :: tys) | ||
| 4952 | algorithm | ||
| 4953 | 23360 | (e, ty) := matchTypes2(e, ty, expected, printFailtrace); | |
| 4954 | 23360 | (exps, tys) := matchTypes_tail(exps, tys, expected, printFailtrace, | |
| 4955 | e :: inAccumExps, ty :: inAccumTypes); | ||
| 4956 | then | ||
| 4957 | (exps, tys); | ||
| 4958 | |||
| 4959 | case ({}, {}) | ||
| 4960 | 8038 | then (listReverse(inAccumExps), listReverse(inAccumTypes)); | |
| 4961 | |||
| 4962 | end match; | ||
| 4963 | end matchTypes_tail; | ||
| 4964 | |||
| 4965 | protected function matchTypes2 | ||
| 4966 | input DAE.Exp inExp; | ||
| 4967 | input DAE.Type inType; | ||
| 4968 | input DAE.Type inExpected; | ||
| 4969 | input Boolean inPrintFailtrace; | ||
| 4970 | output DAE.Exp outExp; | ||
| 4971 | output DAE.Type outType; | ||
| 4972 | algorithm | ||
| 4973 | (outExp, outType) := matchcontinue inPrintFailtrace | ||
| 4974 | local | ||
| 4975 | DAE.Exp e; | ||
| 4976 | DAE.Type ty, expected_ty; | ||
| 4977 | String str; | ||
| 4978 | |||
| 4979 | case _ | ||
| 4980 | algorithm | ||
| 4981 | 23360 | ty := getUniontypeIfMetarecordReplaceAllSubtypes(inType); | |
| 4982 | 23360 | expected_ty := getUniontypeIfMetarecordReplaceAllSubtypes(inExpected); | |
| 4983 | 23360 | (e, ty) := matchType(inExp, ty, expected_ty, inPrintFailtrace); | |
| 4984 | then | ||
| 4985 | (e, ty); | ||
| 4986 | |||
| 4987 | else | ||
| 4988 | algorithm | ||
| 4989 | ✗ | str := "- Types.matchTypes failed for " + ExpressionBasics.printExpStr(inExp) | |
| 4990 | + " from " + TypesDump.unparseType(inType) + " to " + TypesDump.unparseType(inExpected) + "\n"; | ||
| 4991 | ✗ | Error.addMessage(Error.INTERNAL_ERROR, {str}); | |
| 4992 | ✗ | then | |
| 4993 | fail(); | ||
| 4994 | |||
| 4995 | end matchcontinue; | ||
| 4996 | end matchTypes2; | ||
| 4997 | |||
| 4998 | protected function printFailure | ||
| 4999 | "@author adrpo | ||
| 5000 | print the message only when flag is on. | ||
| 5001 | this is to speed up the flattening as we don't | ||
| 5002 | generate the strings at all." | ||
| 5003 | input Flags.DebugFlag flag; | ||
| 5004 | input String source; | ||
| 5005 | input DAE.Exp e; | ||
| 5006 | input DAE.Type e_type; | ||
| 5007 | input DAE.Type expected_type; | ||
| 5008 | algorithm | ||
| 5009 |
1/2✓ Branch 1 taken 461810 times.
✗ Branch 2 not taken.
|
461810 | if Flags.isSet(flag) then |
| 5010 | ✗ | Debug.traceln("- Types." + source + " failed on:" + ExpressionBasics.printExpStr(e)); | |
| 5011 | ✗ | Debug.traceln(" type:" + TypesDump.unparseType(e_type) + " differs from expected\n type:" + TypesDump.unparseType(expected_type)); | |
| 5012 | end if; | ||
| 5013 | end printFailure; | ||
| 5014 | |||
| 5015 | protected function polymorphicBindingStr | ||
| 5016 | input tuple<String,list<DAE.Type>> binding; | ||
| 5017 | output String str; | ||
| 5018 | protected | ||
| 5019 | list<DAE.Type> tys; | ||
| 5020 | algorithm | ||
| 5021 | 6 | (str,tys) := binding; | |
| 5022 | // Don't bother doing this fast; it's just for error messages | ||
| 5023 | 6 | str := " " + str + ":\n" + stringDelimitList(List.map1r(List.map(tys, TypesDump.unparseType), stringAppend, " "), "\n"); | |
| 5024 | end polymorphicBindingStr; | ||
| 5025 | |||
| 5026 | public function polymorphicBindingsStr | ||
| 5027 | input InstTypes.PolymorphicBindings bindings; | ||
| 5028 | output String str; | ||
| 5029 | algorithm | ||
| 5030 | 9 | str := stringDelimitList(List.map(bindings, polymorphicBindingStr), "\n"); | |
| 5031 | end polymorphicBindingsStr; | ||
| 5032 | |||
| 5033 | public function fixPolymorphicRestype | ||
| 5034 | "Uses the polymorphic bindings to determine the result type of the function." | ||
| 5035 | input DAE.Type ty; | ||
| 5036 | input InstTypes.PolymorphicBindings bindings; | ||
| 5037 | input SourceInfo info; | ||
| 5038 | output DAE.Type resType; | ||
| 5039 | algorithm | ||
| 5040 | //print("Trying to fix restype: " + TypesDump.unparseType(ty) + "\n"); | ||
| 5041 | 112221 | resType := fixPolymorphicRestype2(ty,"$",bindings,info); | |
| 5042 | //print("OK: " + TypesDump.unparseType(resType) + "\n"); | ||
| 5043 | end fixPolymorphicRestype; | ||
| 5044 | |||
| 5045 | protected function fixPolymorphicRestype2 | ||
| 5046 | input DAE.Type ty; | ||
| 5047 | input String prefix; | ||
| 5048 | input InstTypes.PolymorphicBindings bindings; | ||
| 5049 | input SourceInfo info; | ||
| 5050 | output DAE.Type resType; | ||
| 5051 | algorithm | ||
| 5052 | resType := matchcontinue ty | ||
| 5053 | local | ||
| 5054 | String id,bstr,tstr; | ||
| 5055 | Type t1,t2,ty1; | ||
| 5056 | list<DAE.Type> tys,tys1; | ||
| 5057 | list<DAE.FuncArg> args1; | ||
| 5058 | DAE.FunctionAttributes functionAttributes; | ||
| 5059 | list<Absyn.Path> paths; | ||
| 5060 | Absyn.Path path; | ||
| 5061 | Boolean knownSingleton; | ||
| 5062 | DAE.EvaluateSingletonType singletonType; | ||
| 5063 | |||
| 5064 | case DAE.T_METAPOLYMORPHIC(name = id) | ||
| 5065 | algorithm | ||
| 5066 |
2/4✗ Branch 2 not taken.
✓ Branch 3 taken 5853 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5853 times.
|
8318 | {t1} := polymorphicBindingsLookup(prefix + id, bindings); |
| 5067 | 5853 | t1 := fixPolymorphicRestype2(t1, "", bindings, info); | |
| 5068 | then t1; | ||
| 5069 | |||
| 5070 | case DAE.T_METALIST(ty = t1) | ||
| 5071 | algorithm | ||
| 5072 | 5187 | t2 := fixPolymorphicRestype2(t1, prefix,bindings, info); | |
| 5073 | 5187 | t2 := boxIfUnboxedType(t2); | |
| 5074 | 5187 | then DAE.T_METALIST(t2); | |
| 5075 | |||
| 5076 | case DAE.T_METAARRAY(ty = t1) | ||
| 5077 | algorithm | ||
| 5078 | 429 | t2 := fixPolymorphicRestype2(t1,prefix,bindings, info); | |
| 5079 | 429 | t2 := boxIfUnboxedType(t2); | |
| 5080 | 429 | then DAE.T_METAARRAY(t2); | |
| 5081 | |||
| 5082 | case DAE.T_METAOPTION(ty = t1) | ||
| 5083 | algorithm | ||
| 5084 | 306 | t2 := fixPolymorphicRestype2(t1, prefix,bindings, info); | |
| 5085 | 306 | t2 := boxIfUnboxedType(t2); | |
| 5086 | 306 | then DAE.T_METAOPTION(t2); | |
| 5087 | |||
| 5088 | case DAE.T_METAUNIONTYPE(typeVars={}) | ||
| 5089 | then ty; | ||
| 5090 | |||
| 5091 | case DAE.T_METAUNIONTYPE(typeVars=tys) | ||
| 5092 | algorithm | ||
| 5093 | 306 | tys := List.map3(tys, fixPolymorphicRestype2, prefix, bindings, info); | |
| 5094 | 306 | tys := List.map(tys, boxIfUnboxedType); | |
| 5095 | 306 | then DAE.T_METAUNIONTYPE(ty.paths,tys,ty.knownSingleton,ty.singletonType,ty.path); | |
| 5096 | |||
| 5097 | case DAE.T_METATUPLE(types = tys) | ||
| 5098 | algorithm | ||
| 5099 | 882 | tys := List.map3(tys, fixPolymorphicRestype2, prefix, bindings, info); | |
| 5100 | 882 | tys := List.map(tys, boxIfUnboxedType); | |
| 5101 | 882 | then DAE.T_METATUPLE(tys); | |
| 5102 | |||
| 5103 | case t1 as DAE.T_ARRAY() | ||
| 5104 | algorithm | ||
| 5105 | 31888 | t1.ty := fixPolymorphicRestype2(t1.ty,prefix,bindings, info); | |
| 5106 | then t1; | ||
| 5107 | |||
| 5108 | case t1 as DAE.T_TUPLE() | ||
| 5109 | algorithm | ||
| 5110 | 3356 | t1.types := List.map3(t1.types, fixPolymorphicRestype2, prefix, bindings, info); | |
| 5111 | then t1; | ||
| 5112 | |||
| 5113 | case DAE.T_FUNCTION(args1,ty1,functionAttributes,path) | ||
| 5114 | algorithm | ||
| 5115 | 56788 | tys1 := List.map(args1, funcArgType); | |
| 5116 | 56788 | tys1 := List.map3(tys1, fixPolymorphicRestype2, prefix, bindings, info); | |
| 5117 | 56788 | ty1 := fixPolymorphicRestype2(ty1,prefix,bindings,info); | |
| 5118 | 56788 | args1 := List.threadMap(args1,tys1,setFuncArgType); | |
| 5119 | 56788 | ty1 := DAE.T_FUNCTION(args1,ty1,functionAttributes,path); | |
| 5120 | then ty1; | ||
| 5121 | |||
| 5122 | // Add Uniontype, Function reference(?) | ||
| 5123 | case _ | ||
| 5124 | algorithm | ||
| 5125 | // failure(isPolymorphic(ty)); Recursive functions like to return polymorphic crap we don't know of | ||
| 5126 | then ty; | ||
| 5127 | |||
| 5128 | else | ||
| 5129 | algorithm | ||
| 5130 | ✗ | tstr := TypesDump.unparseType(ty); | |
| 5131 | ✗ | bstr := polymorphicBindingsStr(bindings); | |
| 5132 | ✗ | id := "Types.fixPolymorphicRestype failed for type: " + tstr + " using bindings: " + bstr; | |
| 5133 | ✗ | Error.addSourceMessage(Error.INTERNAL_ERROR, {id}, info); | |
| 5134 | ✗ | then fail(); | |
| 5135 | end matchcontinue; | ||
| 5136 | end fixPolymorphicRestype2; | ||
| 5137 | |||
| 5138 | public function polymorphicBindingsLookup | ||
| 5139 | input String id; | ||
| 5140 | input InstTypes.PolymorphicBindings bindings; | ||
| 5141 | output list<DAE.Type> resType; | ||
| 5142 | algorithm | ||
| 5143 | resType := matchcontinue bindings | ||
| 5144 | local | ||
| 5145 | String id2; | ||
| 5146 | list<DAE.Type> tys; | ||
| 5147 | InstTypes.PolymorphicBindings rest; | ||
| 5148 | case (id2,tys)::_ | ||
| 5149 | algorithm | ||
| 5150 |
4/4✓ Branch 0 taken 6716 times.
✓ Branch 1 taken 3484 times.
✓ Branch 3 taken 5907 times.
✓ Branch 4 taken 809 times.
|
10200 | true := id == id2; |
| 5151 | 5907 | then List.map(tys, boxIfUnboxedType); | |
| 5152 | case _::rest | ||
| 5153 | algorithm | ||
| 5154 | 4293 | tys := polymorphicBindingsLookup(id,rest); | |
| 5155 | then tys; | ||
| 5156 | end matchcontinue; | ||
| 5157 | end polymorphicBindingsLookup; | ||
| 5158 | |||
| 5159 | public function getAllInnerTypesOfType | ||
| 5160 | "Traverses all the types the input DAE.Type contains, checks if | ||
| 5161 | they are of the type the given function specifies, then returns | ||
| 5162 | a list of all those types." | ||
| 5163 | input DAE.Type inType; | ||
| 5164 | input TypeFn inFn; | ||
| 5165 | output list<DAE.Type> outTypes; | ||
| 5166 | partial function TypeFn | ||
| 5167 | input DAE.Type fnInType; | ||
| 5168 | output Boolean outMatch; | ||
| 5169 | end TypeFn; | ||
| 5170 | algorithm | ||
| 5171 | 163139 | outTypes := getAllInnerTypes({inType},{},inFn); | |
| 5172 | end getAllInnerTypesOfType; | ||
| 5173 | |||
| 5174 | protected function getAllInnerTypes | ||
| 5175 | "Traverses all the types that the input DAE.Type contains, and returns all | ||
| 5176 | types for which the given function returns true." | ||
| 5177 | input list<DAE.Type> inTypes; | ||
| 5178 | input list<DAE.Type> inAccum = {}; | ||
| 5179 | input MatchFunc inFunc; | ||
| 5180 | output list<DAE.Type> outTypes = inAccum; | ||
| 5181 | |||
| 5182 | partial function MatchFunc | ||
| 5183 | input DAE.Type inType; | ||
| 5184 | output Boolean outMatch; | ||
| 5185 | end MatchFunc; | ||
| 5186 | protected | ||
| 5187 | DAE.Type ty; | ||
| 5188 | list<DAE.Type> tys; | ||
| 5189 | algorithm | ||
| 5190 |
2/2✓ Branch 0 taken 293770 times.
✓ Branch 1 taken 456909 times.
|
750679 | for t in inTypes loop |
| 5191 | // Add the type to the result list if the match function return true. | ||
| 5192 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 293770 times.
✓ Branch 4 taken 46412 times.
✓ Branch 5 taken 247358 times.
|
293770 | if inFunc(t) then |
| 5193 | outTypes := t :: outTypes; | ||
| 5194 | end if; | ||
| 5195 | |||
| 5196 | // Get the inner types of the type. | ||
| 5197 | tys := match t | ||
| 5198 | local | ||
| 5199 | list<DAE.Var> fields; | ||
| 5200 | list<DAE.FuncArg> funcArgs; | ||
| 5201 | case DAE.T_ARRAY(ty = ty) then {ty}; | ||
| 5202 | case DAE.T_METALIST(ty = ty) then {ty}; | ||
| 5203 | case DAE.T_METAARRAY(ty = ty) then {ty}; | ||
| 5204 | case DAE.T_METABOXED(ty = ty) then {ty}; | ||
| 5205 | case DAE.T_METAOPTION(ty = ty) then {ty}; | ||
| 5206 | case DAE.T_TUPLE(types = tys) then tys; | ||
| 5207 | case DAE.T_METATUPLE(types = tys) then tys; | ||
| 5208 | case DAE.T_METAUNIONTYPE(typeVars = tys) then tys; | ||
| 5209 | case DAE.T_METARECORD(typeVars = tys, fields = fields) | ||
| 5210 | 17359 | then listAppend(tys, List.map(fields, getVarType)); | |
| 5211 | case DAE.T_COMPLEX(varLst = fields) | ||
| 5212 | 5857 | then List.map(fields, getVarType); | |
| 5213 | case DAE.T_SUBTYPE_BASIC(varLst = fields) | ||
| 5214 | 121 | then List.map(fields, getVarType); | |
| 5215 | case DAE.T_FUNCTION(funcArg = funcArgs, funcResultType = ty) | ||
| 5216 | 1136 | then ty :: List.map(funcArgs, funcArgType); | |
| 5217 | else {}; | ||
| 5218 | end match; | ||
| 5219 | |||
| 5220 | // Call this function recursively to filter out the matching inner types and | ||
| 5221 | // add them to the result. | ||
| 5222 | 293770 | outTypes := getAllInnerTypes(tys, outTypes, inFunc); | |
| 5223 | end for; | ||
| 5224 | end getAllInnerTypes; | ||
| 5225 | |||
| 5226 | public function uniontypeFilter | ||
| 5227 | input DAE.Type ty; | ||
| 5228 | output Boolean outMatch; | ||
| 5229 | algorithm | ||
| 5230 | outMatch := match ty | ||
| 5231 | case DAE.T_METAUNIONTYPE(__) then true; | ||
| 5232 | else false; | ||
| 5233 | end match; | ||
| 5234 | end uniontypeFilter; | ||
| 5235 | |||
| 5236 | public function metarecordFilter | ||
| 5237 | input DAE.Type ty; | ||
| 5238 | output Boolean outMatch; | ||
| 5239 | algorithm | ||
| 5240 | outMatch := match ty | ||
| 5241 | case DAE.T_METARECORD(__) then true; | ||
| 5242 | else false; | ||
| 5243 | end match; | ||
| 5244 | end metarecordFilter; | ||
| 5245 | |||
| 5246 | public function getUniontypePaths | ||
| 5247 | input DAE.Type ty; | ||
| 5248 | output list<Absyn.Path> outPaths; | ||
| 5249 | algorithm | ||
| 5250 | outPaths := match ty | ||
| 5251 | local | ||
| 5252 | list<Absyn.Path> paths; | ||
| 5253 | case DAE.T_METAUNIONTYPE(paths=paths) then paths; | ||
| 5254 | end match; | ||
| 5255 | end getUniontypePaths; | ||
| 5256 | |||
| 5257 | public function makeFunctionPolymorphicReference | ||
| 5258 | "Takes a function reference. If it contains any types that are not boxed, we | ||
| 5259 | return a reference to the function that does take boxed types. Else, we | ||
| 5260 | return a reference to the regular function." | ||
| 5261 | input DAE.Type inType; | ||
| 5262 | output DAE.Type outType; | ||
| 5263 | algorithm | ||
| 5264 | outType := match inType | ||
| 5265 | local | ||
| 5266 | list<DAE.FuncArg> funcArgs1,funcArgs2; | ||
| 5267 | list<DAE.Type> funcArgTypes1, funcArgTypes2, dummyBoxedTypeList; | ||
| 5268 | list<DAE.Exp> dummyExpList; | ||
| 5269 | Type ty2,resType1,resType2; | ||
| 5270 | Absyn.Path path; | ||
| 5271 | DAE.FunctionAttributes functionAttributes; | ||
| 5272 | |||
| 5273 | case DAE.T_FUNCTION(funcArgs1,resType1,functionAttributes,path) | ||
| 5274 | algorithm | ||
| 5275 | 899 | funcArgTypes1 := List.map(funcArgs1, funcArgType); | |
| 5276 | 899 | (dummyExpList,dummyBoxedTypeList) := makeDummyExpAndTypeLists(funcArgTypes1); | |
| 5277 | 899 | (_,funcArgTypes2) := matchTypeTuple(dummyExpList, funcArgTypes1, dummyBoxedTypeList, false); | |
| 5278 | 899 | funcArgs2 := List.threadMap(funcArgs1,funcArgTypes2,setFuncArgType); | |
| 5279 | 899 | resType2 := makeFunctionPolymorphicReferenceResType(resType1); | |
| 5280 | 899 | ty2 := DAE.T_FUNCTION(funcArgs2,resType2,functionAttributes,path); | |
| 5281 | then ty2; | ||
| 5282 | |||
| 5283 | /* Maybe add this case when standard Modelica gets function references? | ||
| 5284 | case (ty1 as (tty1 as DAE.T_FUNCTION(funcArgs1,resType),SOME(path))) | ||
| 5285 | local | ||
| 5286 | list<Boolean> boolList; | ||
| 5287 | algorithm | ||
| 5288 | funcArgTypes1 = List.map(funcArgs1, Util.tuple22); | ||
| 5289 | boolList = List.map(funcArgTypes1, isBoxedType); | ||
| 5290 | true = List.reduce(boolList, boolAnd); | ||
| 5291 | then ty1; */ | ||
| 5292 | case _ | ||
| 5293 | algorithm | ||
| 5294 | // fprintln(Flags.FAILTRACE, "- Types.makeFunctionPolymorphicReference failed"); | ||
| 5295 | then fail(); | ||
| 5296 | end match; | ||
| 5297 | end makeFunctionPolymorphicReference; | ||
| 5298 | |||
| 5299 | protected function makeFunctionPolymorphicReferenceResType | ||
| 5300 | input DAE.Type inType; | ||
| 5301 | output DAE.Type outType; | ||
| 5302 | algorithm | ||
| 5303 | outType := matchcontinue inType | ||
| 5304 | local | ||
| 5305 | DAE.Exp e; | ||
| 5306 | Type ty,ty1,ty2; | ||
| 5307 | list<DAE.Type> tys, dummyBoxedTypeList; | ||
| 5308 | list<DAE.Exp> dummyExpList; | ||
| 5309 | |||
| 5310 | case ty as DAE.T_TUPLE(tys) | ||
| 5311 | algorithm | ||
| 5312 | 101 | (dummyExpList,dummyBoxedTypeList) := makeDummyExpAndTypeLists(tys); | |
| 5313 | 101 | (_,tys) := matchTypeTuple(dummyExpList, tys, dummyBoxedTypeList, false); | |
| 5314 | 101 | ty.types := tys; | |
| 5315 | then ty; | ||
| 5316 | case ty as DAE.T_NORETCALL() then ty; | ||
| 5317 | case ty1 | ||
| 5318 | algorithm | ||
| 5319 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 792 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 792 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 792 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 792 times.
|
792 | ({e},{ty2}) := makeDummyExpAndTypeLists({ty1}); |
| 5320 | 792 | (_,ty) := matchType(e, ty1, ty2, false); | |
| 5321 | 792 | then ty; | |
| 5322 | end matchcontinue; | ||
| 5323 | end makeFunctionPolymorphicReferenceResType; | ||
| 5324 | |||
| 5325 | protected function makeDummyExpAndTypeLists | ||
| 5326 | input list<DAE.Type> lst; | ||
| 5327 | output list<DAE.Exp> outExps; | ||
| 5328 | output list<DAE.Type> outTypes; | ||
| 5329 | algorithm | ||
| 5330 | (outExps,outTypes) := match lst | ||
| 5331 | local | ||
| 5332 | list<DAE.Exp> restExp; | ||
| 5333 | list<DAE.Type> restType, rest; | ||
| 5334 | DAE.ComponentRef cref_; | ||
| 5335 | DAE.Exp crefExp; | ||
| 5336 | |||
| 5337 | case {} then ({},{}); | ||
| 5338 | |||
| 5339 | case _::rest | ||
| 5340 | algorithm | ||
| 5341 | 2360 | (restExp,restType) := makeDummyExpAndTypeLists(rest); | |
| 5342 | 2360 | cref_ := ComponentReferenceBasics.makeCrefIdent("#DummyExp#",DAE.T_UNKNOWN_DEFAULT,{}); | |
| 5343 | 2360 | crefExp := Expression.crefExp(cref_); | |
| 5344 | 2360 | then (crefExp::restExp,DAE.T_METABOXED(DAE.T_UNKNOWN_DEFAULT)::restType); | |
| 5345 | end match; | ||
| 5346 | end makeDummyExpAndTypeLists; | ||
| 5347 | |||
| 5348 | public function resTypeToListTypes | ||
| 5349 | "Transforms a DAE.T_TUPLE to a list of types. Other types return the same type (as a list)" | ||
| 5350 | input DAE.Type inType; | ||
| 5351 | output list<DAE.Type> outType; | ||
| 5352 | algorithm | ||
| 5353 | outType := match inType | ||
| 5354 | local | ||
| 5355 | list<DAE.Type> tys; | ||
| 5356 | Type ty; | ||
| 5357 | case DAE.T_TUPLE(types = tys) then tys; | ||
| 5358 | case DAE.T_NORETCALL() then {}; | ||
| 5359 | case ty then {ty}; | ||
| 5360 | end match; | ||
| 5361 | end resTypeToListTypes; | ||
| 5362 | |||
| 5363 | public function getRealOrIntegerDimensions | ||
| 5364 | "If the type is a Real, Integer or an array of Real or Integer, the function returns | ||
| 5365 | list of dimensions; otherwise, it fails." | ||
| 5366 | input DAE.Type inType; | ||
| 5367 | output DAE.Dimensions outDims; | ||
| 5368 | algorithm | ||
| 5369 | outDims := match inType | ||
| 5370 | local | ||
| 5371 | Type ty; | ||
| 5372 | DAE.Dimension d; | ||
| 5373 | DAE.Dimensions dims; | ||
| 5374 | |||
| 5375 | case DAE.T_REAL() then {}; | ||
| 5376 | case DAE.T_INTEGER() then {}; | ||
| 5377 | case DAE.T_SUBTYPE_BASIC(complexType = ty) | ||
| 5378 | ✗ | then getRealOrIntegerDimensions(ty); | |
| 5379 | |||
| 5380 | case DAE.T_ARRAY(dims = {d as DAE.DIM_INTEGER(_)}, ty = ty) | ||
| 5381 | algorithm | ||
| 5382 | ✗ | dims := getRealOrIntegerDimensions(ty); | |
| 5383 | then | ||
| 5384 | d::dims; | ||
| 5385 | end match; | ||
| 5386 | end getRealOrIntegerDimensions; | ||
| 5387 | |||
| 5388 | public function isPolymorphic | ||
| 5389 | input DAE.Type ty; | ||
| 5390 | output Boolean outMatch; | ||
| 5391 | algorithm | ||
| 5392 | outMatch := match ty | ||
| 5393 | case DAE.T_METAPOLYMORPHIC(__) then true; | ||
| 5394 | else false; | ||
| 5395 | end match; | ||
| 5396 | end isPolymorphic; | ||
| 5397 | |||
| 5398 | public function polymorphicTypeName | ||
| 5399 | input DAE.Type ty; | ||
| 5400 | output String name; | ||
| 5401 | algorithm | ||
| 5402 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | DAE.T_METAPOLYMORPHIC(name = name) := ty; |
| 5403 | end polymorphicTypeName; | ||
| 5404 | |||
| 5405 | public function addPolymorphicBinding | ||
| 5406 | input String id; | ||
| 5407 | input DAE.Type ity; | ||
| 5408 | input InstTypes.PolymorphicBindings bindings; | ||
| 5409 | output InstTypes.PolymorphicBindings outBindings; | ||
| 5410 | algorithm | ||
| 5411 | outBindings := matchcontinue (id,ity,bindings) | ||
| 5412 | local | ||
| 5413 | String id1,id2; | ||
| 5414 | list<DAE.Type> tys; | ||
| 5415 | InstTypes.PolymorphicBindings rest; | ||
| 5416 | tuple<String,list<DAE.Type>> first; | ||
| 5417 | Type ty; | ||
| 5418 | |||
| 5419 | case (_,ty,{}) | ||
| 5420 | algorithm | ||
| 5421 | 2518 | ty := unboxedType(ty); | |
| 5422 | 2518 | ty := boxIfUnboxedType(ty); | |
| 5423 | 2518 | then {(id,{ty})}; | |
| 5424 | case (id1,ty,(id2,tys)::rest) | ||
| 5425 | algorithm | ||
| 5426 |
4/4✓ Branch 0 taken 2072 times.
✓ Branch 1 taken 336 times.
✓ Branch 3 taken 1654 times.
✓ Branch 4 taken 418 times.
|
2408 | true := id1 == id2; |
| 5427 | 1654 | ty := unboxedType(ty); | |
| 5428 | 1654 | ty := boxIfUnboxedType(ty); | |
| 5429 | 1654 | then (id2,ty::tys)::rest; | |
| 5430 | case (_,ty,first::rest) | ||
| 5431 | algorithm | ||
| 5432 | 754 | rest := addPolymorphicBinding(id,ty,rest); | |
| 5433 | then first::rest; | ||
| 5434 | end matchcontinue; | ||
| 5435 | end addPolymorphicBinding; | ||
| 5436 | |||
| 5437 | public function solvePolymorphicBindings | ||
| 5438 | "Takes a set of polymorphic bindings and tries to solve the constraints | ||
| 5439 | such that each name is bound to a non-polymorphic type. | ||
| 5440 | Solves by doing iterations until a valid state is found (or no change is | ||
| 5441 | possible)." | ||
| 5442 | input InstTypes.PolymorphicBindings bindings; | ||
| 5443 | input SourceInfo info; | ||
| 5444 | input Absyn.Path path; | ||
| 5445 | output InstTypes.PolymorphicBindings solvedBindings; | ||
| 5446 | protected | ||
| 5447 | InstTypes.PolymorphicBindings unsolvedBindings; | ||
| 5448 | algorithm | ||
| 5449 | // print("solvePoly " + polymorphicBindingsStr(bindings) + "\n"); | ||
| 5450 | 56006 | (solvedBindings,unsolvedBindings) := solvePolymorphicBindingsLoop(bindings, {}, {}); | |
| 5451 | 56006 | checkValidBindings(bindings, solvedBindings, unsolvedBindings, info, path); | |
| 5452 | // print("solved poly " + polymorphicBindingsStr(solvedBindings) + "\n"); | ||
| 5453 | end solvePolymorphicBindings; | ||
| 5454 | |||
| 5455 | protected function checkValidBindings | ||
| 5456 | "Emits an error message if we could not solve the polymorphic types to actual types." | ||
| 5457 | input InstTypes.PolymorphicBindings bindings; | ||
| 5458 | input InstTypes.PolymorphicBindings solvedBindings; | ||
| 5459 | input InstTypes.PolymorphicBindings unsolvedBindings; | ||
| 5460 | input SourceInfo info; | ||
| 5461 | input Absyn.Path path; | ||
| 5462 | protected | ||
| 5463 | String bindingsStr, solvedBindingsStr, unsolvedBindingsStr, pathStr; | ||
| 5464 | algorithm | ||
| 5465 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 56003 times.
|
56006 | if not listEmpty(unsolvedBindings) then |
| 5466 | 3 | pathStr := AbsynUtil.pathString(path); | |
| 5467 | 3 | bindingsStr := polymorphicBindingsStr(bindings); | |
| 5468 | 3 | solvedBindingsStr := polymorphicBindingsStr(solvedBindings); | |
| 5469 | 3 | unsolvedBindingsStr := polymorphicBindingsStr(unsolvedBindings); | |
| 5470 | 3 | Error.addSourceMessage(Error.META_UNSOLVED_POLYMORPHIC_BINDINGS, {pathStr,bindingsStr,solvedBindingsStr,unsolvedBindingsStr},info); | |
| 5471 | 3 | fail(); | |
| 5472 | end if; | ||
| 5473 | end checkValidBindings; | ||
| 5474 | |||
| 5475 | protected function solvePolymorphicBindingsLoop | ||
| 5476 | input InstTypes.PolymorphicBindings ibindings; | ||
| 5477 | input InstTypes.PolymorphicBindings isolvedBindings; | ||
| 5478 | input InstTypes.PolymorphicBindings iunsolvedBindings; | ||
| 5479 | output InstTypes.PolymorphicBindings outSolvedBindings; | ||
| 5480 | output InstTypes.PolymorphicBindings outUnsolvedBindings; | ||
| 5481 | algorithm | ||
| 5482 | (outSolvedBindings,outUnsolvedBindings) := matchcontinue (ibindings,isolvedBindings,iunsolvedBindings) | ||
| 5483 | /* Fail by returning crap :) */ | ||
| 5484 | local | ||
| 5485 | tuple<String, list<DAE.Type>> first; | ||
| 5486 | Type ty; | ||
| 5487 | list<DAE.Type> tys; | ||
| 5488 | String id; | ||
| 5489 | Integer len1, len2; | ||
| 5490 | InstTypes.PolymorphicBindings rest,solvedBindings,unsolvedBindings; | ||
| 5491 | |||
| 5492 | 56006 | case ({}, solvedBindings, unsolvedBindings) then (solvedBindings, unsolvedBindings); | |
| 5493 | |||
| 5494 | case ((id,{ty})::rest,solvedBindings,unsolvedBindings) | ||
| 5495 | algorithm | ||
| 5496 | 2452 | ty := Types.boxIfUnboxedType(ty); | |
| 5497 | 2452 | (solvedBindings,unsolvedBindings) := solvePolymorphicBindingsLoop(listAppend(unsolvedBindings,rest),(id,{ty})::solvedBindings,{}); | |
| 5498 | then (solvedBindings,unsolvedBindings); | ||
| 5499 | |||
| 5500 | // Replace solved bindings | ||
| 5501 | case ((id,tys)::rest,solvedBindings,unsolvedBindings) | ||
| 5502 | algorithm | ||
| 5503 | 1201 | tys := replaceSolvedBindings(tys, solvedBindings, false); | |
| 5504 | 46 | tys := List.unionOnTrue(tys, {}, equivtypes); | |
| 5505 | 92 | (solvedBindings,unsolvedBindings) := solvePolymorphicBindingsLoop(listAppend((id,tys)::unsolvedBindings,rest),solvedBindings,{}); | |
| 5506 | then (solvedBindings,unsolvedBindings); | ||
| 5507 | |||
| 5508 | case ((id,tys)::rest,solvedBindings,unsolvedBindings) | ||
| 5509 | algorithm | ||
| 5510 | 1155 | (tys,solvedBindings) := solveBindings(tys, tys, solvedBindings); | |
| 5511 | 63 | tys := List.unionOnTrue(tys, {}, equivtypes); | |
| 5512 | 126 | (solvedBindings,unsolvedBindings) := solvePolymorphicBindingsLoop(listAppend((id,tys)::unsolvedBindings,rest),solvedBindings,{}); | |
| 5513 | then (solvedBindings,unsolvedBindings); | ||
| 5514 | |||
| 5515 | // Duplicate types need to be removed | ||
| 5516 | case ((id,tys)::rest,solvedBindings,unsolvedBindings) | ||
| 5517 | algorithm | ||
| 5518 | 1092 | len1 := listLength(tys); | |
| 5519 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1092 times.
|
1092 | true := len1 > 1; |
| 5520 | 1092 | tys := List.unionOnTrue(tys, {}, equivtypes); // Remove duplicates | |
| 5521 | 1092 | len2 := listLength(tys); | |
| 5522 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1089 times.
|
1092 | false := len1 == len2; |
| 5523 | 2178 | (solvedBindings,unsolvedBindings) := solvePolymorphicBindingsLoop(listAppend((id,tys)::unsolvedBindings,rest),solvedBindings,{}); | |
| 5524 | then (solvedBindings,unsolvedBindings); | ||
| 5525 | |||
| 5526 | case (first::rest, solvedBindings, unsolvedBindings) | ||
| 5527 | algorithm | ||
| 5528 | 3 | (solvedBindings,unsolvedBindings) := solvePolymorphicBindingsLoop(rest, solvedBindings, first::unsolvedBindings); | |
| 5529 | then (solvedBindings, unsolvedBindings); | ||
| 5530 | end matchcontinue; | ||
| 5531 | end solvePolymorphicBindingsLoop; | ||
| 5532 | |||
| 5533 | protected function solveBindings | ||
| 5534 | "Checks all types against each other to find an unbound polymorphic variable, which will then become bound. | ||
| 5535 | Uses unification to solve the system, but the algorithm is slow (possibly quadratic). | ||
| 5536 | The good news is we don't have functions with many unknown types in the compiler. | ||
| 5537 | Horribly complicated function to keep track of what happens..." | ||
| 5538 | input list<DAE.Type> itys1; | ||
| 5539 | input list<DAE.Type> itys2; | ||
| 5540 | input InstTypes.PolymorphicBindings isolvedBindings; | ||
| 5541 | output list<DAE.Type> outTys; | ||
| 5542 | output InstTypes.PolymorphicBindings outSolvedBindings; | ||
| 5543 | algorithm | ||
| 5544 | (outTys,outSolvedBindings) := matchcontinue (itys1,itys2,isolvedBindings) | ||
| 5545 | local | ||
| 5546 | Type ty,ty1,ty2; | ||
| 5547 | list<DAE.Type> tys,rest,tys1,tys2; | ||
| 5548 | String id,id1,id2; | ||
| 5549 | list<DAE.FuncArg> args1,args2; | ||
| 5550 | DAE.FunctionAttributes functionAttributes1; | ||
| 5551 | Absyn.Path path; | ||
| 5552 | Boolean fromOtherFunction; | ||
| 5553 | InstTypes.PolymorphicBindings solvedBindings; | ||
| 5554 | |||
| 5555 | case ((ty1 as DAE.T_METAPOLYMORPHIC(name = id1))::_,(ty2 as DAE.T_METAPOLYMORPHIC(name = id2))::tys2,solvedBindings) | ||
| 5556 | algorithm | ||
| 5557 |
4/4✓ Branch 0 taken 986 times.
✓ Branch 1 taken 24 times.
✓ Branch 3 taken 978 times.
✓ Branch 4 taken 8 times.
|
1010 | false := id1 == id2; |
| 5558 | // If we have $X,Y,..., bind $X = Y instead of Y = $X | ||
| 5559 | 32 | fromOtherFunction := System.stringFind(id1,"$") <> -1; | |
| 5560 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 15 times.
|
32 | id := if fromOtherFunction then id1 else id2; |
| 5561 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 15 times.
|
32 | ty := if fromOtherFunction then ty2 else ty1; // Lookup from one id to the other type |
| 5562 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 30 times.
|
62 | failure(polymorphicBindingsLookup(id, solvedBindings)); |
| 5563 | 30 | solvedBindings := addPolymorphicBinding(id,ty,solvedBindings); | |
| 5564 | 30 | then (ty::tys2, solvedBindings); | |
| 5565 | |||
| 5566 | case ((DAE.T_METAPOLYMORPHIC(name = id))::_,ty2::tys2,solvedBindings) | ||
| 5567 | algorithm | ||
| 5568 |
2/2✓ Branch 1 taken 980 times.
✓ Branch 2 taken 28 times.
|
1008 | false := isPolymorphic(ty2); |
| 5569 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 28 times.
|
56 | failure(polymorphicBindingsLookup(id, solvedBindings)); |
| 5570 | 28 | solvedBindings := addPolymorphicBinding(id,ty2,solvedBindings); | |
| 5571 | 28 | then (ty2::tys2, solvedBindings); | |
| 5572 | |||
| 5573 | case (ty1::_,(DAE.T_METAPOLYMORPHIC(name = id))::tys2,solvedBindings) | ||
| 5574 | algorithm | ||
| 5575 |
2/2✓ Branch 1 taken 980 times.
✓ Branch 2 taken 5 times.
|
985 | false := isPolymorphic(ty1); |
| 5576 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
|
10 | failure(polymorphicBindingsLookup(id, solvedBindings)); |
| 5577 | 5 | solvedBindings := addPolymorphicBinding(id,ty1,solvedBindings); | |
| 5578 | 5 | then (ty1::tys2, solvedBindings); | |
| 5579 | |||
| 5580 | case (DAE.T_METAOPTION(ty = ty1)::_,DAE.T_METAOPTION(ty = ty2)::tys2,solvedBindings) | ||
| 5581 | algorithm | ||
| 5582 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
|
30 | ({ty1},solvedBindings) := solveBindings({ty1},{ty2},solvedBindings); |
| 5583 | 1 | ty1 := DAE.T_METAOPTION(ty1); | |
| 5584 | 1 | then (ty1::tys2,solvedBindings); | |
| 5585 | |||
| 5586 | case (DAE.T_METALIST(ty = ty1)::_,DAE.T_METALIST(ty = ty2)::tys2,solvedBindings) | ||
| 5587 | algorithm | ||
| 5588 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
|
188 | ({ty1},solvedBindings) := solveBindings({ty1},{ty2},solvedBindings); |
| 5589 | 4 | ty1 := DAE.T_METALIST(ty1); | |
| 5590 | 4 | then (ty1::tys2,solvedBindings); | |
| 5591 | |||
| 5592 | case (DAE.T_METAARRAY(ty = ty1)::_,DAE.T_METAARRAY(ty = ty2)::tys2,solvedBindings) | ||
| 5593 | algorithm | ||
| 5594 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
|
7 | ({ty1},solvedBindings) := solveBindings({ty1},{ty2},solvedBindings); |
| 5595 | 1 | ty1 := DAE.T_METAARRAY(ty1); | |
| 5596 | 1 | then (ty1::tys2,solvedBindings); | |
| 5597 | |||
| 5598 | case (DAE.T_METATUPLE(types = tys1)::_,DAE.T_METATUPLE(types = tys2)::rest,solvedBindings) | ||
| 5599 | algorithm | ||
| 5600 | 62 | (tys1,solvedBindings) := solveBindingsThread(tys1,tys2,false,solvedBindings); | |
| 5601 | 2 | ty1 := DAE.T_METATUPLE(tys1); | |
| 5602 | 2 | then (ty1::rest,solvedBindings); | |
| 5603 | |||
| 5604 | case (DAE.T_FUNCTION(args1,ty1,functionAttributes1,path)::_,DAE.T_FUNCTION(args2,ty2,_,_)::rest,solvedBindings) | ||
| 5605 | algorithm | ||
| 5606 | 9 | tys1 := List.map(args1, funcArgType); | |
| 5607 | 9 | tys2 := List.map(args2, funcArgType); | |
| 5608 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
9 | (ty1::tys1,solvedBindings) := solveBindingsThread(ty1::tys1,ty2::tys2,false,solvedBindings); |
| 5609 | 3 | tys1 := List.map(tys1, boxIfUnboxedType); | |
| 5610 | 3 | args1 := List.threadMap(args1,tys1,setFuncArgType); | |
| 5611 | 3 | args1 := List.map(args1,clearDefaultBinding); | |
| 5612 | 3 | ty1 := DAE.T_FUNCTION(args1,ty1,functionAttributes1,path); | |
| 5613 | 3 | then (ty1::rest,solvedBindings); | |
| 5614 | |||
| 5615 | case (tys1,ty::tys2,solvedBindings) | ||
| 5616 | algorithm | ||
| 5617 | 3112 | (tys,solvedBindings) := solveBindings(tys1,tys2,solvedBindings); | |
| 5618 | 69 | then (ty::tys,solvedBindings); | |
| 5619 | end matchcontinue; | ||
| 5620 | end solveBindings; | ||
| 5621 | |||
| 5622 | protected function solveBindingsThread | ||
| 5623 | "Checks all types against each other to find an unbound polymorphic variable, which will then become bound. | ||
| 5624 | Uses unification to solve the system, but the algorithm is slow (possibly quadratic). | ||
| 5625 | The good news is we don't have functions with many unknown types in the compiler. | ||
| 5626 | |||
| 5627 | Horribly complicated function to keep track of what happens..." | ||
| 5628 | input list<DAE.Type> itys1; | ||
| 5629 | input list<DAE.Type> itys2; | ||
| 5630 | input Boolean changed "if true, something changed and the function will succeed"; | ||
| 5631 | input InstTypes.PolymorphicBindings isolvedBindings; | ||
| 5632 | output list<DAE.Type> outTys; | ||
| 5633 | output InstTypes.PolymorphicBindings outSolvedBindings; | ||
| 5634 | algorithm | ||
| 5635 | (outTys,outSolvedBindings) := matchcontinue (itys1,itys2,changed,isolvedBindings) | ||
| 5636 | local | ||
| 5637 | Type ty1,ty2; | ||
| 5638 | InstTypes.PolymorphicBindings solvedBindings; | ||
| 5639 | list<DAE.Type> tys1, tys2; | ||
| 5640 | |||
| 5641 | case (ty1::tys1,ty2::tys2,_,solvedBindings) | ||
| 5642 | algorithm | ||
| 5643 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
|
187 | ({ty1},solvedBindings) := solveBindings({ty1},{ty2},solvedBindings); |
| 5644 | 5 | (tys2,solvedBindings) := solveBindingsThread(tys1,tys2,true,solvedBindings); | |
| 5645 | 5 | then (ty1::tys2,solvedBindings); | |
| 5646 | case (ty1::tys1,_::tys2,_,solvedBindings) | ||
| 5647 | algorithm | ||
| 5648 | 182 | (tys2,solvedBindings) := solveBindingsThread(tys1,tys2,changed,solvedBindings); | |
| 5649 | 8 | then (ty1::tys2,solvedBindings); | |
| 5650 | case ({},{},true,solvedBindings) then ({},solvedBindings); | ||
| 5651 | end matchcontinue; | ||
| 5652 | end solveBindingsThread; | ||
| 5653 | |||
| 5654 | protected function replaceSolvedBindings | ||
| 5655 | input list<DAE.Type> itys; | ||
| 5656 | input InstTypes.PolymorphicBindings isolvedBindings; | ||
| 5657 | input Boolean changed "if true, something changed and the function will succeed"; | ||
| 5658 | output list<DAE.Type> outTys; | ||
| 5659 | algorithm | ||
| 5660 | outTys := matchcontinue (itys, isolvedBindings, changed) | ||
| 5661 | local | ||
| 5662 | Type ty; | ||
| 5663 | list<DAE.Type> tys; | ||
| 5664 | InstTypes.PolymorphicBindings solvedBindings; | ||
| 5665 | |||
| 5666 | case ({},_,true) then {}; | ||
| 5667 | case (ty::tys,solvedBindings,_) | ||
| 5668 | algorithm | ||
| 5669 | 3182 | ty := replaceSolvedBinding(ty,solvedBindings); | |
| 5670 | 58 | tys := replaceSolvedBindings(tys,solvedBindings,true); | |
| 5671 | then ty::tys; | ||
| 5672 | case (ty::tys,solvedBindings,_) | ||
| 5673 | algorithm | ||
| 5674 | 3124 | tys := replaceSolvedBindings(tys,solvedBindings,changed); | |
| 5675 | then ty::tys; | ||
| 5676 | end matchcontinue; | ||
| 5677 | end replaceSolvedBindings; | ||
| 5678 | |||
| 5679 | protected function replaceSolvedBinding | ||
| 5680 | input DAE.Type ity; | ||
| 5681 | input InstTypes.PolymorphicBindings isolvedBindings; | ||
| 5682 | output DAE.Type outTy; | ||
| 5683 | algorithm | ||
| 5684 | outTy := match (ity,isolvedBindings) | ||
| 5685 | local | ||
| 5686 | list<DAE.FuncArg> args; | ||
| 5687 | list<DAE.Type> tys; | ||
| 5688 | String id; | ||
| 5689 | list<String> names; | ||
| 5690 | Absyn.Path path; | ||
| 5691 | DAE.FunctionAttributes functionAttributes; | ||
| 5692 | DAE.Type ty,resType; | ||
| 5693 | InstTypes.PolymorphicBindings solvedBindings; | ||
| 5694 | |||
| 5695 | case (DAE.T_METALIST(ty = ty),solvedBindings) | ||
| 5696 | algorithm | ||
| 5697 | 205 | ty := replaceSolvedBinding(ty, solvedBindings); | |
| 5698 | 5 | ty := DAE.T_METALIST(ty); | |
| 5699 | then ty; | ||
| 5700 | |||
| 5701 | case (DAE.T_METAARRAY(ty = ty),solvedBindings) | ||
| 5702 | algorithm | ||
| 5703 | 9 | ty := replaceSolvedBinding(ty, solvedBindings); | |
| 5704 | 1 | ty := DAE.T_METAARRAY(ty); | |
| 5705 | then ty; | ||
| 5706 | |||
| 5707 | case (DAE.T_METAOPTION(ty = ty),solvedBindings) | ||
| 5708 | algorithm | ||
| 5709 | 32 | ty := replaceSolvedBinding(ty, solvedBindings); | |
| 5710 | 1 | ty := DAE.T_METAOPTION(ty); | |
| 5711 | then ty; | ||
| 5712 | |||
| 5713 | case (DAE.T_METATUPLE(types = tys),solvedBindings) | ||
| 5714 | algorithm | ||
| 5715 | 74 | tys := replaceSolvedBindings(tys,solvedBindings,false); | |
| 5716 | 2 | ty := DAE.T_METATUPLE(tys); | |
| 5717 | then ty; | ||
| 5718 | |||
| 5719 | case (DAE.T_TUPLE(types = tys),solvedBindings) | ||
| 5720 | algorithm | ||
| 5721 | 12 | tys := replaceSolvedBindings(tys,solvedBindings,false); | |
| 5722 | 2 | ty := DAE.T_TUPLE(tys,ity.names); | |
| 5723 | then ty; | ||
| 5724 | |||
| 5725 | case (DAE.T_FUNCTION(args,resType,functionAttributes,path),solvedBindings) | ||
| 5726 | algorithm | ||
| 5727 | 15 | tys := List.map(args, funcArgType); | |
| 5728 | 15 | tys := replaceSolvedBindings(resType::tys,solvedBindings,false); | |
| 5729 | 2 | tys := List.map(tys, unboxedType); | |
| 5730 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | ty::tys := List.map(tys, boxIfUnboxedType); |
| 5731 | 2 | args := List.threadMap(args,tys,setFuncArgType); | |
| 5732 | 2 | ty := makeRegularTupleFromMetaTupleOnTrue(isTuple(resType),ty); | |
| 5733 | 2 | ty := DAE.T_FUNCTION(args,ty,functionAttributes,path); | |
| 5734 | then ty; | ||
| 5735 | |||
| 5736 | case (DAE.T_METAPOLYMORPHIC(name = id),solvedBindings) | ||
| 5737 | algorithm | ||
| 5738 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 52 times.
|
1151 | {ty} := polymorphicBindingsLookup(id, solvedBindings); |
| 5739 | then ty; | ||
| 5740 | end match; | ||
| 5741 | end replaceSolvedBinding; | ||
| 5742 | |||
| 5743 | protected function subtypePolymorphic | ||
| 5744 | "A simple subtype() that also binds polymorphic variables. | ||
| 5745 | Only works on the MetaModelica datatypes; the input is assumed to be boxed. | ||
| 5746 | " | ||
| 5747 | input DAE.Type actual; | ||
| 5748 | input DAE.Type expected; | ||
| 5749 | input Option<Absyn.Path> envPath; | ||
| 5750 | input InstTypes.PolymorphicBindings inBindings; | ||
| 5751 | output InstTypes.PolymorphicBindings bindings; | ||
| 5752 | algorithm | ||
| 5753 | bindings := matchcontinue (actual,expected) | ||
| 5754 | local | ||
| 5755 | String id,prefix; | ||
| 5756 | Type ty,ty1,ty2; | ||
| 5757 | list<DAE.FuncArg> farg1,farg2; | ||
| 5758 | list<DAE.Type> tList1,tList2,tys; | ||
| 5759 | Absyn.Path path1,path2; | ||
| 5760 | list<String> ids,names1,names2; | ||
| 5761 | |||
| 5762 | case (_,DAE.T_METAPOLYMORPHIC(name = id)) | ||
| 5763 | 4091 | then addPolymorphicBinding("$" + id,actual,inBindings); | |
| 5764 | |||
| 5765 | case (DAE.T_METAPOLYMORPHIC(name = id),_) | ||
| 5766 | algorithm | ||
| 5767 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 5 times.
|
15 | if stringGet(id,1)<>stringCharInt("$") then |
| 5768 | // We allow things like inner type variables of function pointers, | ||
| 5769 | // but not things like accepting T1 can be tuple<T2,T3>. | ||
| 5770 | // print("Not adding METAPOLYMORPHIC $$"+id+"="+TypesDump.unparseType(expected)+"\n"); | ||
| 5771 | 10 | fail(); | |
| 5772 | end if; | ||
| 5773 | 5 | then addPolymorphicBinding("$$" + id,expected,inBindings); | |
| 5774 | |||
| 5775 | case (DAE.T_METABOXED(ty = ty1),ty2) | ||
| 5776 | algorithm | ||
| 5777 | 446 | ty1 := unboxedType(ty1); | |
| 5778 | 446 | then subtypePolymorphic(ty1,ty2,envPath,inBindings); | |
| 5779 | |||
| 5780 | case (ty1,DAE.T_METABOXED(ty = ty2)) | ||
| 5781 | algorithm | ||
| 5782 | 307 | ty2 := unboxedType(ty2); | |
| 5783 | 307 | then subtypePolymorphic(ty1,ty2,envPath,inBindings); | |
| 5784 | |||
| 5785 | case (DAE.T_NORETCALL(),DAE.T_NORETCALL()) then inBindings; | ||
| 5786 | case (DAE.T_INTEGER(),DAE.T_INTEGER()) then inBindings; | ||
| 5787 | case (DAE.T_REAL(),DAE.T_INTEGER()) then inBindings; | ||
| 5788 | case (DAE.T_STRING(),DAE.T_STRING()) then inBindings; | ||
| 5789 | case (DAE.T_BOOL(),DAE.T_BOOL()) then inBindings; | ||
| 5790 | |||
| 5791 | case (DAE.T_ENUMERATION(names = names1), | ||
| 5792 | DAE.T_ENUMERATION(names = names2)) | ||
| 5793 | algorithm | ||
| 5794 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
|
46 | true := List.isEqualOnTrue(names1, names2, stringEq); |
| 5795 | then inBindings; | ||
| 5796 | |||
| 5797 | case (DAE.T_ARRAY(ty = ty1),DAE.T_ARRAY(ty = ty2)) | ||
| 5798 | 139 | then subtypePolymorphic(ty1,ty2,envPath,inBindings); | |
| 5799 | |||
| 5800 | case (DAE.T_METAARRAY(ty = ty1),DAE.T_METAARRAY(ty = ty2)) | ||
| 5801 | 146 | then subtypePolymorphic(ty1,ty2,envPath,inBindings); | |
| 5802 | case (DAE.T_METALIST(ty = ty1),DAE.T_METALIST(ty = ty2)) | ||
| 5803 | 1042 | then subtypePolymorphic(ty1,ty2,envPath,inBindings); | |
| 5804 | case (DAE.T_METAOPTION(ty = ty1),DAE.T_METAOPTION(ty = ty2)) | ||
| 5805 | 32 | then subtypePolymorphic(ty1,ty2,envPath,inBindings); | |
| 5806 | case (DAE.T_METATUPLE(types = tList1),DAE.T_METATUPLE(types = tList2)) | ||
| 5807 | 147 | then subtypePolymorphicList(tList1,tList2,envPath,inBindings); | |
| 5808 | |||
| 5809 | case (DAE.T_TUPLE(types = tList1),DAE.T_TUPLE(types = tList2)) | ||
| 5810 | 209 | then subtypePolymorphicList(tList1,tList2,envPath,inBindings); | |
| 5811 | |||
| 5812 | case (DAE.T_METAUNIONTYPE(),DAE.T_METAUNIONTYPE()) | ||
| 5813 | algorithm | ||
| 5814 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 662 times.
|
662 | true := AbsynUtil.pathEqual(actual.path, expected.path); |
| 5815 | 662 | then subtypePolymorphicList(actual.typeVars, expected.typeVars, envPath, inBindings); | |
| 5816 | |||
| 5817 | case (DAE.T_COMPLEX(complexClassType = ClassInf.EXTERNAL_OBJ(path1)),DAE.T_COMPLEX(complexClassType = ClassInf.EXTERNAL_OBJ(path2))) | ||
| 5818 | algorithm | ||
| 5819 | ✗ | true := AbsynUtil.pathEqual(path1,path2); | |
| 5820 | then inBindings; | ||
| 5821 | |||
| 5822 | // MM Function Reference. sjoelund | ||
| 5823 | case (DAE.T_FUNCTION(farg1,ty1,_,path1),DAE.T_FUNCTION(farg2,ty2,_,_)) | ||
| 5824 | algorithm | ||
| 5825 |
2/2✓ Branch 2 taken 299 times.
✓ Branch 3 taken 360 times.
|
659 | if AbsynUtil.pathPrefixOf(Util.getOptionOrDefault(envPath,Absyn.IDENT("$TOP$")),path1) then // Don't rename the result type for recursive calls... |
| 5826 | 299 | tList1 := List.map(farg1, funcArgType); | |
| 5827 | 299 | tList2 := List.map(farg2, funcArgType); | |
| 5828 | 299 | bindings := subtypePolymorphicList(tList1,tList2,envPath,inBindings); | |
| 5829 | 299 | bindings := subtypePolymorphic(ty1,ty2,envPath,bindings); | |
| 5830 | else | ||
| 5831 | 360 | prefix := "$" + AbsynUtil.pathString(path1) + "."; | |
| 5832 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 360 times.
|
360 | (DAE.T_FUNCTION(farg1,ty1,_,_),_) := traverseType(actual, prefix, prefixTraversedPolymorphicType); |
| 5833 | 360 | tList1 := List.map(farg1, funcArgType); | |
| 5834 | 360 | tList2 := List.map(farg2, funcArgType); | |
| 5835 | 360 | bindings := subtypePolymorphicList(tList1,tList2,envPath,inBindings); | |
| 5836 | 360 | bindings := subtypePolymorphic(ty1,ty2,envPath,bindings); | |
| 5837 | end if; | ||
| 5838 | then bindings; | ||
| 5839 | |||
| 5840 | case (DAE.T_UNKNOWN(),ty2) | ||
| 5841 | algorithm | ||
| 5842 | 9 | tys := getAllInnerTypesOfType(ty2, isPolymorphic); | |
| 5843 | 9 | ids := List.map(tys, polymorphicTypeName); | |
| 5844 | 9 | bindings := List.fold1(ids, addPolymorphicBinding, actual, inBindings); | |
| 5845 | then bindings; | ||
| 5846 | |||
| 5847 | case (DAE.T_ANYTYPE(),ty2) | ||
| 5848 | algorithm | ||
| 5849 | ✗ | tys := getAllInnerTypesOfType(ty2, isPolymorphic); | |
| 5850 | ✗ | ids := List.map(tys, polymorphicTypeName); | |
| 5851 | ✗ | bindings := List.fold1(ids, addPolymorphicBinding, actual, inBindings); | |
| 5852 | then bindings; | ||
| 5853 | |||
| 5854 | else | ||
| 5855 | algorithm | ||
| 5856 | // print("subtypePolymorphic failed: " + TypesDump.unparseType(actual) + " and " + TypesDump.unparseType(expected) + "\n"); | ||
| 5857 | then fail(); | ||
| 5858 | |||
| 5859 | end matchcontinue; | ||
| 5860 | end subtypePolymorphic; | ||
| 5861 | |||
| 5862 | protected function subtypePolymorphicList | ||
| 5863 | "A simple subtype() that also binds polymorphic variables. | ||
| 5864 | Only works on the MetaModelica datatypes; the input is assumed to be boxed." | ||
| 5865 | input list<DAE.Type> actual; | ||
| 5866 | input list<DAE.Type> expected; | ||
| 5867 | input Option<Absyn.Path> envPath; | ||
| 5868 | input InstTypes.PolymorphicBindings ibindings; | ||
| 5869 | output InstTypes.PolymorphicBindings outBindings; | ||
| 5870 | algorithm | ||
| 5871 | outBindings := match (actual, expected, ibindings) | ||
| 5872 | local | ||
| 5873 | Type ty1,ty2; | ||
| 5874 | list<DAE.Type> tList1,tList2; | ||
| 5875 | InstTypes.PolymorphicBindings bindings; | ||
| 5876 | case ({}, {}, bindings) then bindings; | ||
| 5877 | case (ty1::tList1, ty2::tList2, bindings) | ||
| 5878 | algorithm | ||
| 5879 | 2165 | bindings := subtypePolymorphic(ty1,ty2,envPath,bindings); | |
| 5880 | 2165 | bindings := subtypePolymorphicList(tList1,tList2,envPath,bindings); | |
| 5881 | then bindings; | ||
| 5882 | end match; | ||
| 5883 | end subtypePolymorphicList; | ||
| 5884 | |||
| 5885 | public function boxVarLst | ||
| 5886 | input list<DAE.Var> vars; | ||
| 5887 | output list<DAE.Var> ovars; | ||
| 5888 | algorithm | ||
| 5889 | ovars := match vars | ||
| 5890 | local | ||
| 5891 | String name; | ||
| 5892 | DAE.Attributes attributes; | ||
| 5893 | DAE.Type type_; | ||
| 5894 | DAE.Binding binding; | ||
| 5895 | Boolean bdsrc; | ||
| 5896 | Option<DAE.Const> constOfForIteratorRange; | ||
| 5897 | list<DAE.Var> rest; | ||
| 5898 | |||
| 5899 | case {} then {}; | ||
| 5900 | case DAE.TYPES_VAR(name,attributes,type_,binding,bdsrc,constOfForIteratorRange)::rest | ||
| 5901 | algorithm | ||
| 5902 | 92252 | type_ := boxIfUnboxedType(type_); | |
| 5903 | 92252 | rest := boxVarLst(rest); | |
| 5904 |
1/2✓ Branch 0 taken 92252 times.
✗ Branch 1 not taken.
|
184504 | then DAE.TYPES_VAR(name,attributes,type_,binding,bdsrc,constOfForIteratorRange)::rest; |
| 5905 | |||
| 5906 | end match; | ||
| 5907 | end boxVarLst; | ||
| 5908 | |||
| 5909 | public function liftArraySubscript "Lifts a type to an array using DAE.Subscript for dimension in the case of non-expanded arrays" | ||
| 5910 | input DAE.Type inType; | ||
| 5911 | input DAE.Subscript inSubscript; | ||
| 5912 | output DAE.Type outType; | ||
| 5913 | algorithm | ||
| 5914 | outType := match (inType,inSubscript) | ||
| 5915 | local | ||
| 5916 | Type ty; | ||
| 5917 | Integer i; | ||
| 5918 | DAE.Exp e; | ||
| 5919 | |||
| 5920 | // An array with an explicit dimension | ||
| 5921 | case (ty,DAE.WHOLE_NONEXP(exp=DAE.ICONST(i))) | ||
| 5922 | ✗ | then DAE.T_ARRAY(ty, {DAE.DIM_INTEGER(i)}); | |
| 5923 | |||
| 5924 | // An array with parametric dimension | ||
| 5925 | case (ty,DAE.WHOLE_NONEXP(exp = e)) | ||
| 5926 | ✗ | then DAE.T_ARRAY(ty,{DAE.DIM_EXP(e)}); | |
| 5927 | |||
| 5928 | // All other kinds of subscripts denote an index, so the type stays the same | ||
| 5929 | case (ty,_) | ||
| 5930 | then ty; | ||
| 5931 | end match; | ||
| 5932 | end liftArraySubscript; | ||
| 5933 | |||
| 5934 | public function liftArraySubscriptList " | ||
| 5935 | Lifts a type using list<DAE.Subscript> to determine dimensions in the case of non-expanded arrays" | ||
| 5936 | input DAE.Type inType; | ||
| 5937 | input list<DAE.Subscript> inSubscriptLst; | ||
| 5938 | output DAE.Type outType; | ||
| 5939 | algorithm | ||
| 5940 | outType := match (inType,inSubscriptLst) | ||
| 5941 | local | ||
| 5942 | Type ty; | ||
| 5943 | DAE.Subscript sub; | ||
| 5944 | list<DAE.Subscript> rest; | ||
| 5945 | case (ty,{}) then ty; | ||
| 5946 | ✗ | case (ty,sub::rest) then liftArraySubscript(liftArraySubscriptList(ty,rest),sub); | |
| 5947 | end match; | ||
| 5948 | end liftArraySubscriptList; | ||
| 5949 | |||
| 5950 | public function convertTupleToMetaTuple "Needed when pattern-matching" | ||
| 5951 | input DAE.Exp exp; | ||
| 5952 | input DAE.Type ty; | ||
| 5953 | output DAE.Exp oexp; | ||
| 5954 | output DAE.Type oty; | ||
| 5955 | algorithm | ||
| 5956 | (oexp,oty) := match exp | ||
| 5957 | case DAE.TUPLE(_) | ||
| 5958 | algorithm | ||
| 5959 | /* So we can verify that the contents of the tuple is boxed */ | ||
| 5960 | ✗ | (oexp,oty) := matchType(exp,ty,DAE.T_METABOXED_DEFAULT,false); | |
| 5961 | then (oexp,oty); | ||
| 5962 | 675 | else (exp,ty); | |
| 5963 | end match; | ||
| 5964 | end convertTupleToMetaTuple; | ||
| 5965 | |||
| 5966 | public function isFunctionType | ||
| 5967 | input DAE.Type ty; | ||
| 5968 | output Boolean b; | ||
| 5969 | algorithm | ||
| 5970 | b := match ty | ||
| 5971 | case DAE.T_FUNCTION() then true; | ||
| 5972 | else false; | ||
| 5973 | end match; | ||
| 5974 | end isFunctionType; | ||
| 5975 | |||
| 5976 | protected function prefixTraversedPolymorphicType | ||
| 5977 | input Type ty; | ||
| 5978 | input String prefix; | ||
| 5979 | output Type oty = ty; | ||
| 5980 | output String str; | ||
| 5981 | algorithm | ||
| 5982 | (oty,str) := match oty | ||
| 5983 | case DAE.T_METAPOLYMORPHIC() | ||
| 5984 | algorithm | ||
| 5985 | 146 | oty.name := prefix + oty.name; | |
| 5986 | then (oty,prefix); | ||
| 5987 | else (ty,prefix); | ||
| 5988 | end match; | ||
| 5989 | end prefixTraversedPolymorphicType; | ||
| 5990 | |||
| 5991 | public function makeExpDimensionsUnknown | ||
| 5992 | input DAE.Type ty; | ||
| 5993 | input Integer dummy; | ||
| 5994 | output DAE.Type oty = ty; | ||
| 5995 | output Integer odummy = dummy; | ||
| 5996 | algorithm | ||
| 5997 | oty := match oty | ||
| 5998 | case DAE.T_ARRAY(dims={DAE.DIM_EXP()}) | ||
| 5999 | algorithm | ||
| 6000 | 196 | oty.dims := {DAE.DIM_UNKNOWN()}; | |
| 6001 | then oty; | ||
| 6002 | else oty; | ||
| 6003 | end match; | ||
| 6004 | end makeExpDimensionsUnknown; | ||
| 6005 | |||
| 6006 | public function makeKnownDimensionsInteger "In binding equations, [Boolean] and [2] match, so we need to convert them" | ||
| 6007 | input DAE.Type ty; | ||
| 6008 | input Integer dummy; | ||
| 6009 | output DAE.Type oty = ty; | ||
| 6010 | output Integer odummy = dummy; | ||
| 6011 | algorithm | ||
| 6012 | oty := match oty | ||
| 6013 | local | ||
| 6014 | Integer size; | ||
| 6015 | case DAE.T_ARRAY(dims={DAE.DIM_BOOLEAN()}) | ||
| 6016 | algorithm | ||
| 6017 | ✗ | oty.dims := {DAE.DIM_INTEGER(2)}; | |
| 6018 | then oty; | ||
| 6019 | case DAE.T_ARRAY(dims={DAE.DIM_ENUM(size=size)}) | ||
| 6020 | algorithm | ||
| 6021 | ✗ | oty.dims := {DAE.DIM_INTEGER(size)}; | |
| 6022 | then oty; | ||
| 6023 | case DAE.T_ARRAY(dims={DAE.DIM_EXP(exp=DAE.ICONST(size))}) | ||
| 6024 | algorithm | ||
| 6025 | ✗ | oty.dims := {DAE.DIM_INTEGER(size)}; | |
| 6026 | then oty; | ||
| 6027 | else oty; | ||
| 6028 | end match; | ||
| 6029 | end makeKnownDimensionsInteger; | ||
| 6030 | |||
| 6031 | public function traverseType | ||
| 6032 | input DAE.Type ty; | ||
| 6033 | input A arg; | ||
| 6034 | input Func fn; | ||
| 6035 | output DAE.Type oty; | ||
| 6036 | output A a = arg; | ||
| 6037 | replaceable type A subtypeof Any; | ||
| 6038 | partial function Func | ||
| 6039 | input DAE.Type ty; | ||
| 6040 | input A arg; | ||
| 6041 | output DAE.Type oty; | ||
| 6042 | output A oarg; | ||
| 6043 | end Func; | ||
| 6044 | algorithm | ||
| 6045 | (oty,a) := match ty | ||
| 6046 | local | ||
| 6047 | list<DAE.Type> tys; | ||
| 6048 | Type tyInner; | ||
| 6049 | String str; | ||
| 6050 | list<DAE.Var> vars; | ||
| 6051 | list<DAE.FuncArg> farg; | ||
| 6052 | |||
| 6053 | case DAE.T_INTEGER() then (ty,a); | ||
| 6054 | case DAE.T_REAL() then (ty,a); | ||
| 6055 | case DAE.T_STRING() then (ty,a); | ||
| 6056 | case DAE.T_BOOL() then (ty,a); | ||
| 6057 | case DAE.T_CLOCK() then (ty,a); | ||
| 6058 | case DAE.T_ENUMERATION() then (ty,a); | ||
| 6059 | case DAE.T_NORETCALL() then (ty,a); | ||
| 6060 | case DAE.T_UNKNOWN() then (ty,a); | ||
| 6061 | case DAE.T_METAUNIONTYPE() then (ty,a); | ||
| 6062 | case DAE.T_METAPOLYMORPHIC() then (ty,a); | ||
| 6063 | case DAE.T_CODE() then (ty,a); | ||
| 6064 | |||
| 6065 | case oty as DAE.T_METABOXED() | ||
| 6066 | algorithm | ||
| 6067 | 31046 | (tyInner,a) := traverseType(oty.ty, a, fn); | |
| 6068 | 31046 | oty.ty := tyInner; | |
| 6069 | 31046 | then (oty,a); | |
| 6070 | case oty as DAE.T_ARRAY() | ||
| 6071 | algorithm | ||
| 6072 | 411736 | (tyInner,a) := traverseType(oty.ty, a, fn); | |
| 6073 | 411736 | oty.ty := tyInner; | |
| 6074 | 411736 | then (oty,a); | |
| 6075 | case oty as DAE.T_METATYPE() | ||
| 6076 | algorithm | ||
| 6077 | 63 | (tyInner,a) := traverseType(oty.ty, a, fn); | |
| 6078 | 63 | oty.ty := tyInner; | |
| 6079 | 63 | then (oty,a); | |
| 6080 | case oty as DAE.T_METALIST() | ||
| 6081 | algorithm | ||
| 6082 | 35858 | (tyInner, a) := traverseType(oty.ty, a, fn); | |
| 6083 | 35858 | oty.ty := tyInner; | |
| 6084 | 35858 | then (oty,a); | |
| 6085 | case oty as DAE.T_METAOPTION() | ||
| 6086 | algorithm | ||
| 6087 | 21336 | (tyInner,a) := traverseType(oty.ty, a, fn); | |
| 6088 | 21336 | oty.ty := tyInner; | |
| 6089 | 21336 | then (oty,a); | |
| 6090 | case oty as DAE.T_METAARRAY() | ||
| 6091 | algorithm | ||
| 6092 | 1585 | (tyInner,a) := traverseType(oty.ty, a, fn); | |
| 6093 | 1585 | oty.ty := tyInner; | |
| 6094 | 1585 | then (oty,a); | |
| 6095 | case oty as DAE.T_FUNCTION_REFERENCE_VAR() | ||
| 6096 | algorithm | ||
| 6097 | ✗ | (tyInner,a) := traverseType(oty.functionType, a, fn); | |
| 6098 | ✗ | oty.functionType := tyInner; | |
| 6099 | ✗ | then (oty,a); | |
| 6100 | case oty as DAE.T_FUNCTION_REFERENCE_FUNC() | ||
| 6101 | algorithm | ||
| 6102 | ✗ | (tyInner,a) := traverseType(oty.functionType, a, fn); | |
| 6103 | ✗ | oty.functionType := tyInner; | |
| 6104 | ✗ | then (oty,a); | |
| 6105 | |||
| 6106 | case oty as DAE.T_METATUPLE() | ||
| 6107 | algorithm | ||
| 6108 | 17626 | (tys,a) := traverseTupleType(oty.types, a, fn); | |
| 6109 | 17626 | oty.types := tys; | |
| 6110 | 17626 | then (oty,a); | |
| 6111 | case oty as DAE.T_TUPLE() | ||
| 6112 | algorithm | ||
| 6113 | 5575 | (tys,a) := traverseTupleType(oty.types, a, fn); | |
| 6114 | 5575 | oty.types := tys; | |
| 6115 | 5575 | then (oty, a); | |
| 6116 | |||
| 6117 | case oty as DAE.T_METARECORD() | ||
| 6118 | algorithm | ||
| 6119 | 35063 | (vars, a) := traverseVarTypes(oty.fields, a, fn); | |
| 6120 | 35063 | oty.fields := vars; | |
| 6121 | 35063 | then (oty, a); | |
| 6122 | case oty as DAE.T_COMPLEX() | ||
| 6123 | algorithm | ||
| 6124 | 94703 | (vars, a) := traverseVarTypes(oty.varLst, a, fn); | |
| 6125 | 94703 | oty.varLst := vars; | |
| 6126 | 94703 | then (oty, a); | |
| 6127 | |||
| 6128 | case oty as DAE.T_SUBTYPE_BASIC() | ||
| 6129 | algorithm | ||
| 6130 | 47977 | (vars, a) := traverseVarTypes(oty.varLst, a, fn); | |
| 6131 | 47977 | (tyInner,a) := traverseType(oty.complexType, a, fn); | |
| 6132 | 47977 | oty.varLst := vars; | |
| 6133 | 47977 | oty.complexType := tyInner; | |
| 6134 | 47977 | then (oty, a); | |
| 6135 | |||
| 6136 | case oty as DAE.T_FUNCTION() | ||
| 6137 | algorithm | ||
| 6138 | 3913 | (farg, a) := traverseFuncArg(oty.funcArg, a, fn); | |
| 6139 | 3913 | (tyInner, a) := traverseType(oty.funcResultType, a, fn); | |
| 6140 | 3913 | oty.funcArg := farg; | |
| 6141 | 3913 | oty.funcResultType := tyInner; | |
| 6142 | 3913 | then (oty, a); | |
| 6143 | |||
| 6144 | else | ||
| 6145 | algorithm | ||
| 6146 | ✗ | str := "Types.traverseType not implemented correctly: " + TypesDump.unparseType(ty); | |
| 6147 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{str}); | |
| 6148 | ✗ | then | |
| 6149 | fail(); | ||
| 6150 | end match; | ||
| 6151 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2539902 times.
|
2539902 | (oty, a) := fn(oty, a); |
| 6152 | end traverseType; | ||
| 6153 | |||
| 6154 | protected function traverseTupleType | ||
| 6155 | input list<DAE.Type> itys; | ||
| 6156 | input A ia; | ||
| 6157 | input Func fn; | ||
| 6158 | output list<DAE.Type> otys; | ||
| 6159 | output A oa; | ||
| 6160 | replaceable type A subtypeof Any; | ||
| 6161 | partial function Func | ||
| 6162 | input DAE.Type ty; | ||
| 6163 | input A arg; | ||
| 6164 | output DAE.Type oty; | ||
| 6165 | output A oarg; | ||
| 6166 | end Func; | ||
| 6167 | algorithm | ||
| 6168 | (otys,oa) := match (itys, ia) | ||
| 6169 | local | ||
| 6170 | Type ty; | ||
| 6171 | list<DAE.Type> tys; | ||
| 6172 | A a; | ||
| 6173 | |||
| 6174 | case ({}, a) then ({},a); | ||
| 6175 | case (ty::tys, a) | ||
| 6176 | algorithm | ||
| 6177 | 49303 | (ty,a) := traverseType(ty, a, fn); | |
| 6178 | 49303 | (tys,a) := traverseTupleType(tys, a, fn); | |
| 6179 | 49303 | then (ty::tys,a); | |
| 6180 | end match; | ||
| 6181 | end traverseTupleType; | ||
| 6182 | |||
| 6183 | protected function traverseVarTypes | ||
| 6184 | input list<DAE.Var> ivars; | ||
| 6185 | input A ia; | ||
| 6186 | input Func fn; | ||
| 6187 | output list<DAE.Var> ovars; | ||
| 6188 | output A oa; | ||
| 6189 | replaceable type A subtypeof Any; | ||
| 6190 | partial function Func | ||
| 6191 | input DAE.Type ty; | ||
| 6192 | input A arg; | ||
| 6193 | output DAE.Type oty; | ||
| 6194 | output A oarg; | ||
| 6195 | end Func; | ||
| 6196 | algorithm | ||
| 6197 | (ovars,oa) := match (ivars, ia) | ||
| 6198 | local | ||
| 6199 | DAE.Var var; | ||
| 6200 | DAE.Type ty; | ||
| 6201 | list<DAE.Var> vars; | ||
| 6202 | A a; | ||
| 6203 | |||
| 6204 | case ({}, a) then ({},a); | ||
| 6205 | case (var::vars, a) | ||
| 6206 | algorithm | ||
| 6207 | 668441 | ty := getVarType(var); | |
| 6208 | 668441 | (ty, a) := traverseType(ty, a, fn); | |
| 6209 | 668441 | var := setVarType(var,ty); | |
| 6210 | 668441 | (vars,a) := traverseVarTypes(vars,a,fn); | |
| 6211 | 668441 | then (var::vars,a); | |
| 6212 | end match; | ||
| 6213 | end traverseVarTypes; | ||
| 6214 | |||
| 6215 | protected function traverseFuncArg | ||
| 6216 | input list<DAE.FuncArg> iargs; | ||
| 6217 | input A ia; | ||
| 6218 | input Func fn; | ||
| 6219 | output list<DAE.FuncArg> oargs; | ||
| 6220 | output A oa; | ||
| 6221 | replaceable type A subtypeof Any; | ||
| 6222 | partial function Func | ||
| 6223 | input DAE.Type ty; | ||
| 6224 | input A arg; | ||
| 6225 | output DAE.Type oty; | ||
| 6226 | output A oarg; | ||
| 6227 | end Func; | ||
| 6228 | algorithm | ||
| 6229 | (oargs,oa) := match (iargs,ia) | ||
| 6230 | local | ||
| 6231 | list<DAE.FuncArg> args; | ||
| 6232 | A a; | ||
| 6233 | DAE.FuncArg arg; | ||
| 6234 | DAE.Type ty; | ||
| 6235 | |||
| 6236 | case ({},a) then ({},a); | ||
| 6237 | case ((arg as DAE.FUNCARG())::args,a) | ||
| 6238 | algorithm | ||
| 6239 | 6039 | (ty, a) := traverseType(arg.ty, a, fn); | |
| 6240 | 6039 | arg.ty := ty; | |
| 6241 | 6039 | (args,a) := traverseFuncArg(args,a,fn); | |
| 6242 | 6039 | then (arg::args, a); | |
| 6243 | end match; | ||
| 6244 | end traverseFuncArg; | ||
| 6245 | |||
| 6246 | public function makeRegularTupleFromMetaTupleOnTrue | ||
| 6247 | input Boolean b; | ||
| 6248 | input DAE.Type ty; | ||
| 6249 | output DAE.Type out; | ||
| 6250 | algorithm | ||
| 6251 | out := match (b,ty) | ||
| 6252 | local | ||
| 6253 | list<DAE.Type> tys; | ||
| 6254 | |||
| 6255 | case (true,DAE.T_METATUPLE(tys)) | ||
| 6256 | algorithm | ||
| 6257 | 146 | tys := List.mapMap(tys, unboxedType, boxIfUnboxedType); | |
| 6258 | 146 | tys := List.map(tys, unboxedType); // Yes. Crazy | |
| 6259 | 146 | then (DAE.T_TUPLE(tys,NONE())); | |
| 6260 | |||
| 6261 | case (false,_) then ty; | ||
| 6262 | end match; | ||
| 6263 | end makeRegularTupleFromMetaTupleOnTrue; | ||
| 6264 | |||
| 6265 | public function allTuple | ||
| 6266 | input list<DAE.Type> itys; | ||
| 6267 | output Boolean b; | ||
| 6268 | algorithm | ||
| 6269 | b := match itys local list<DAE.Type> tys; | ||
| 6270 | case {} then true; | ||
| 6271 | 695 | case DAE.T_TUPLE()::tys then allTuple(tys); | |
| 6272 | else false; | ||
| 6273 | end match; | ||
| 6274 | end allTuple; | ||
| 6275 | |||
| 6276 | public function unboxedFunctionType "For DAE.PARTEVALFUNC" | ||
| 6277 | input DAE.Type inType; | ||
| 6278 | output DAE.Type outType; | ||
| 6279 | algorithm | ||
| 6280 | outType := match inType | ||
| 6281 | local | ||
| 6282 | list<DAE.FuncArg> args1; | ||
| 6283 | list<DAE.Type> tys1; | ||
| 6284 | Type ty1; | ||
| 6285 | DAE.FunctionAttributes functionAttributes; | ||
| 6286 | Absyn.Path path; | ||
| 6287 | |||
| 6288 | case DAE.T_FUNCTION(args1,ty1,functionAttributes,path) | ||
| 6289 | algorithm | ||
| 6290 | ✗ | tys1 := List.mapMap(args1, funcArgType, unboxedType); | |
| 6291 | ✗ | ty1 := unboxedType(ty1); | |
| 6292 | ✗ | args1 := List.threadMap(args1,tys1,setFuncArgType); | |
| 6293 | ✗ | then (DAE.T_FUNCTION(args1,ty1,functionAttributes,path)); | |
| 6294 | end match; | ||
| 6295 | end unboxedFunctionType; | ||
| 6296 | |||
| 6297 | public function varHasMetaRecordType | ||
| 6298 | input DAE.Var var; | ||
| 6299 | output Boolean b; | ||
| 6300 | algorithm | ||
| 6301 | b := match var | ||
| 6302 | case DAE.TYPES_VAR(ty = DAE.T_METABOXED(ty = DAE.T_METARECORD())) | ||
| 6303 | then true; | ||
| 6304 | case DAE.TYPES_VAR(ty = DAE.T_METARECORD()) | ||
| 6305 | then true; | ||
| 6306 | case DAE.TYPES_VAR(ty = DAE.T_METABOXED(ty = DAE.T_COMPLEX(complexClassType = ClassInf.META_RECORD(_)))) | ||
| 6307 | then true; | ||
| 6308 | else false; | ||
| 6309 | end match; | ||
| 6310 | end varHasMetaRecordType; | ||
| 6311 | |||
| 6312 | protected function optInteger | ||
| 6313 | input Option<Integer> inInt; | ||
| 6314 | output Integer outInt; | ||
| 6315 | algorithm | ||
| 6316 | outInt := match inInt | ||
| 6317 | local Integer i; | ||
| 6318 | case SOME(i) then i; | ||
| 6319 | else -1; | ||
| 6320 | end match; | ||
| 6321 | end optInteger; | ||
| 6322 | |||
| 6323 | public function typeToValue "This function builds Values.Value out of a type using generated bindings." | ||
| 6324 | input DAE.Type inType; | ||
| 6325 | output Values.Value defaultValue; | ||
| 6326 | algorithm | ||
| 6327 | defaultValue := matchcontinue inType | ||
| 6328 | local | ||
| 6329 | list<DAE.Var> vars; | ||
| 6330 | list<String> comp; | ||
| 6331 | ClassInf.State st; | ||
| 6332 | Type t; | ||
| 6333 | list<DAE.Type> tys; | ||
| 6334 | String s1; | ||
| 6335 | Absyn.Path path; | ||
| 6336 | Integer i; | ||
| 6337 | Option<Integer> iOpt; | ||
| 6338 | Values.Value v; | ||
| 6339 | list<Values.Value> valueLst, ordered; | ||
| 6340 | |||
| 6341 | case DAE.T_INTEGER() then Values.INTEGER(0); | ||
| 6342 | case DAE.T_REAL() then Values.REAL(0.0); | ||
| 6343 | case DAE.T_STRING() then Values.STRING("<EMPTY>"); | ||
| 6344 | case DAE.T_BOOL() then Values.BOOL(false); | ||
| 6345 | case DAE.T_ENUMERATION(index = iOpt, path = path) | ||
| 6346 | algorithm | ||
| 6347 | ✗ | i := optInteger(iOpt); | |
| 6348 | ✗ | then | |
| 6349 | Values.ENUM_LITERAL(path, i); | ||
| 6350 | |||
| 6351 | case DAE.T_COMPLEX(complexClassType = st,varLst = vars) | ||
| 6352 | algorithm | ||
| 6353 | 2624 | (ordered, comp) := varsToValues(vars); | |
| 6354 | 2624 | path := ClassInfUtil.getStateName(st); | |
| 6355 | 2624 | then | |
| 6356 | Values.RECORD(path, ordered, comp, -1); | ||
| 6357 | |||
| 6358 | case DAE.T_SUBTYPE_BASIC(complexType = t) | ||
| 6359 | algorithm | ||
| 6360 | ✗ | v := typeToValue(t); | |
| 6361 | then | ||
| 6362 | v; | ||
| 6363 | |||
| 6364 | case DAE.T_ARRAY(dims = {DAE.DIM_INTEGER(i)},ty = t) | ||
| 6365 | algorithm | ||
| 6366 | 7788 | v := typeToValue(t); | |
| 6367 | 7788 | valueLst := List.fill(v, i); | |
| 6368 | 7788 | then | |
| 6369 | Values.ARRAY(valueLst, {i}); | ||
| 6370 | |||
| 6371 | case DAE.T_TUPLE(types = tys) | ||
| 6372 | algorithm | ||
| 6373 | ✗ | valueLst := List.map(tys, typeToValue); | |
| 6374 | ✗ | v := Values.TUPLE(valueLst); | |
| 6375 | then | ||
| 6376 | v; | ||
| 6377 | |||
| 6378 | case DAE.T_UNKNOWN() then Values.META_FAIL(); | ||
| 6379 | |||
| 6380 | |||
| 6381 | // All the other ones we don't handle | ||
| 6382 | else | ||
| 6383 | algorithm | ||
| 6384 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 6385 | ✗ | Debug.trace("- Types.typeToValue failed on unhandled Type "); | |
| 6386 | ✗ | s1 := TypesDump.printTypeStr(inType); | |
| 6387 | ✗ | Debug.traceln(s1); | |
| 6388 | ✗ | then | |
| 6389 | fail(); | ||
| 6390 | |||
| 6391 | end matchcontinue; | ||
| 6392 | end typeToValue; | ||
| 6393 | |||
| 6394 | public function varsToValues "Translates a list of Var list to Values.Value, the | ||
| 6395 | names of the variables as component names. | ||
| 6396 | Used e.g. when retrieving the type of a record value." | ||
| 6397 | input list<DAE.Var> inVarLst; | ||
| 6398 | output list<Values.Value> outValuesValueLst; | ||
| 6399 | output list<String> outExpIdentLst; | ||
| 6400 | algorithm | ||
| 6401 | (outValuesValueLst,outExpIdentLst) := matchcontinue inVarLst | ||
| 6402 | local | ||
| 6403 | DAE.Type tp; | ||
| 6404 | list<DAE.Var> rest; | ||
| 6405 | Values.Value v; | ||
| 6406 | list<Values.Value> restVals; | ||
| 6407 | String id; | ||
| 6408 | list<String> restIds; | ||
| 6409 | |||
| 6410 | case {} then ({}, {}); | ||
| 6411 | |||
| 6412 | case DAE.TYPES_VAR(name = id,ty = tp)::rest | ||
| 6413 | algorithm | ||
| 6414 | 7928 | v := typeToValue(tp); | |
| 6415 | 7928 | (restVals, restIds) := varsToValues(rest); | |
| 6416 | 7928 | then | |
| 6417 | (v::restVals, id::restIds); | ||
| 6418 | |||
| 6419 | else | ||
| 6420 | algorithm | ||
| 6421 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 6422 | ✗ | Debug.trace("- Types.varsToValues failed\n"); | |
| 6423 | ✗ | then | |
| 6424 | fail(); | ||
| 6425 | end matchcontinue; | ||
| 6426 | end varsToValues; | ||
| 6427 | |||
| 6428 | public function makeNthDimUnknown | ||
| 6429 | "Real [3,2,1],3 => Real [3,2,:]" | ||
| 6430 | input DAE.Type ty; | ||
| 6431 | input Integer dim; | ||
| 6432 | output DAE.Type oty; | ||
| 6433 | algorithm | ||
| 6434 | oty := match (ty,dim) | ||
| 6435 | local | ||
| 6436 | DAE.Dimension ad; | ||
| 6437 | Type ty1; | ||
| 6438 | |||
| 6439 | 156 | case (DAE.T_ARRAY(ty1,{_}),1) then DAE.T_ARRAY(ty1,{DAE.DIM_UNKNOWN()}); | |
| 6440 | case (DAE.T_ARRAY(ty1,{ad}),_) | ||
| 6441 | algorithm | ||
| 6442 | 5 | ty1 := makeNthDimUnknown(ty1,dim-1); | |
| 6443 | 5 | then | |
| 6444 | DAE.T_ARRAY(ty1,{ad}); | ||
| 6445 | end match; | ||
| 6446 | end makeNthDimUnknown; | ||
| 6447 | |||
| 6448 | public function arraySuperType | ||
| 6449 | "Selects the supertype out of two array-types. Integer may be promoted to Real." | ||
| 6450 | input DAE.Type ity1; | ||
| 6451 | input SourceInfo info; | ||
| 6452 | input DAE.Type ity2; | ||
| 6453 | output DAE.Type ty; | ||
| 6454 | algorithm | ||
| 6455 | ty := matchcontinue (ity1, ity2) | ||
| 6456 | local | ||
| 6457 | String str1,str2; | ||
| 6458 | Type ty1, ty2; | ||
| 6459 | case (ty1, ty2) | ||
| 6460 | algorithm | ||
| 6461 |
2/2✓ Branch 2 taken 82 times.
✓ Branch 3 taken 5 times.
|
87 | true := isInteger(arrayElementType(ty1)); |
| 6462 |
2/2✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
|
5 | true := isReal(arrayElementType(ty2)); |
| 6463 | 3 | ty1 := traverseType(ty1, -1, replaceIntegerTypeWithReal); | |
| 6464 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | true := subtype(ty1,ty2); |
| 6465 | then ty1; | ||
| 6466 | case (ty1, ty2) | ||
| 6467 | algorithm | ||
| 6468 |
2/2✓ Branch 2 taken 82 times.
✓ Branch 3 taken 2 times.
|
84 | true := isInteger(arrayElementType(ty2)); |
| 6469 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | true := isReal(arrayElementType(ty1)); |
| 6470 | ✗ | ty2 := traverseType(ty2, -1, replaceIntegerTypeWithReal); | |
| 6471 | ✗ | true := subtype(ty1,ty2); | |
| 6472 | then ty1; | ||
| 6473 | case (ty1, ty2) | ||
| 6474 | algorithm | ||
| 6475 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
|
84 | true := subtype(ty1,ty2); |
| 6476 | then ty1; | ||
| 6477 | case (ty1, ty2) | ||
| 6478 | algorithm | ||
| 6479 | ✗ | str1 := TypesDump.unparseType(ty1); | |
| 6480 | ✗ | str2 := TypesDump.unparseType(ty2); | |
| 6481 | ✗ | typeErrorSanityCheck(str1, str2, info); | |
| 6482 | ✗ | Error.addSourceMessage(Error.ARRAY_TYPE_MISMATCH,{str1,str2},info); | |
| 6483 | ✗ | then fail(); | |
| 6484 | end matchcontinue; | ||
| 6485 | end arraySuperType; | ||
| 6486 | |||
| 6487 | protected function replaceIntegerTypeWithReal | ||
| 6488 | input Type ty; | ||
| 6489 | input Integer dummy; | ||
| 6490 | output Type oty; | ||
| 6491 | output Integer odummy = dummy; | ||
| 6492 | algorithm | ||
| 6493 | oty := match ty | ||
| 6494 | case DAE.T_INTEGER() then DAE.T_REAL_DEFAULT; | ||
| 6495 | else ty; | ||
| 6496 | end match; | ||
| 6497 | end replaceIntegerTypeWithReal; | ||
| 6498 | |||
| 6499 | public function isZeroLengthArray | ||
| 6500 | input DAE.Type ty; | ||
| 6501 | output Boolean res; | ||
| 6502 | algorithm | ||
| 6503 | res := match ty | ||
| 6504 | local | ||
| 6505 | list<DAE.Dimension> dims; | ||
| 6506 | case DAE.T_ARRAY(dims = dims) | ||
| 6507 | algorithm | ||
| 6508 | 124344 | res := List.fold(dims, isZeroDim, false); | |
| 6509 | then res; | ||
| 6510 | else false; | ||
| 6511 | end match; | ||
| 6512 | end isZeroLengthArray; | ||
| 6513 | |||
| 6514 | protected function isZeroDim "Check dimensions by folding and checking for zeroes" | ||
| 6515 | input DAE.Dimension dim; | ||
| 6516 | input Boolean acc; | ||
| 6517 | output Boolean res; | ||
| 6518 | algorithm | ||
| 6519 | res := match dim | ||
| 6520 | case DAE.DIM_INTEGER(integer=0) then true; | ||
| 6521 | case DAE.DIM_ENUM(size=0) then true; | ||
| 6522 | else acc; | ||
| 6523 | end match; | ||
| 6524 | end isZeroDim; | ||
| 6525 | |||
| 6526 | public function variabilityToConst "translates an SCode.Variability to a DAE.Const" | ||
| 6527 | input SCode.Variability variability; | ||
| 6528 | output DAE.Const const; | ||
| 6529 | algorithm | ||
| 6530 | const := match variability | ||
| 6531 | case SCode.VAR() then DAE.C_VAR(); | ||
| 6532 | case SCode.DISCRETE() then DAE.C_VAR(); | ||
| 6533 | case SCode.PARAM() then DAE.C_PARAM(); | ||
| 6534 | case SCode.CONST() then DAE.C_CONST(); | ||
| 6535 | end match; | ||
| 6536 | end variabilityToConst; | ||
| 6537 | |||
| 6538 | public function varKindToConst "translates an DAE.varKind to a DAE.Const" | ||
| 6539 | input DAE.VarKind varKind; | ||
| 6540 | output DAE.Const const; | ||
| 6541 | algorithm | ||
| 6542 | const := match varKind | ||
| 6543 | case DAE.VARIABLE() then DAE.C_VAR(); | ||
| 6544 | case DAE.DISCRETE() then DAE.C_VAR(); | ||
| 6545 | case DAE.PARAM() then DAE.C_PARAM(); | ||
| 6546 | case DAE.CONST() then DAE.C_CONST(); | ||
| 6547 | end match; | ||
| 6548 | end varKindToConst; | ||
| 6549 | |||
| 6550 | public function isValidFunctionVarType | ||
| 6551 | input DAE.Type inType; | ||
| 6552 | output Boolean outIsValid; | ||
| 6553 | algorithm | ||
| 6554 | outIsValid := match inType | ||
| 6555 | local | ||
| 6556 | Type ty; | ||
| 6557 | ClassInf.State state; | ||
| 6558 | |||
| 6559 | case DAE.T_COMPLEX(complexClassType = state) | ||
| 6560 | 5622 | then isValidFunctionVarState(state); | |
| 6561 | |||
| 6562 | case DAE.T_SUBTYPE_BASIC(complexType = ty) | ||
| 6563 | 28 | then isValidFunctionVarType(ty); | |
| 6564 | |||
| 6565 | else true; | ||
| 6566 | |||
| 6567 | end match; | ||
| 6568 | end isValidFunctionVarType; | ||
| 6569 | |||
| 6570 | protected function isValidFunctionVarState | ||
| 6571 | input ClassInf.State inState; | ||
| 6572 | output Boolean outIsValid; | ||
| 6573 | algorithm | ||
| 6574 | outIsValid := match inState | ||
| 6575 | case ClassInf.MODEL() then false; | ||
| 6576 | case ClassInf.BLOCK() then false; | ||
| 6577 | case ClassInf.CONNECTOR() then false; | ||
| 6578 | case ClassInf.OPTIMIZATION() then false; | ||
| 6579 | case ClassInf.PACKAGE() then false; | ||
| 6580 | else true; | ||
| 6581 | end match; | ||
| 6582 | end isValidFunctionVarState; | ||
| 6583 | |||
| 6584 | protected function makeDummyExpFromType | ||
| 6585 | "Creates a dummy expression from a type. Used by typeConvertArray to handle | ||
| 6586 | empty arrays." | ||
| 6587 | input DAE.Type inType; | ||
| 6588 | output DAE.Exp outExp; | ||
| 6589 | algorithm | ||
| 6590 | outExp := match inType | ||
| 6591 | local | ||
| 6592 | Type ty; | ||
| 6593 | DAE.Dimension dim; | ||
| 6594 | Integer idim; | ||
| 6595 | DAE.Exp exp; | ||
| 6596 | list<DAE.Exp> expl; | ||
| 6597 | DAE.Type ety; | ||
| 6598 | |||
| 6599 | case DAE.T_INTEGER() then DAE.ICONST(0); | ||
| 6600 | case DAE.T_REAL() then DAE.RCONST(0.0); | ||
| 6601 | case DAE.T_STRING() then DAE.SCONST(""); | ||
| 6602 | case DAE.T_BOOL() then DAE.BCONST(false); | ||
| 6603 | ✗ | case DAE.T_ENUMERATION() then getNthEnumLiteral(inType, 1); | |
| 6604 | case DAE.T_ARRAY(ty = ty, dims = {dim}) | ||
| 6605 | algorithm | ||
| 6606 | 23 | idim := Expression.dimensionSize(dim); | |
| 6607 | 23 | exp := makeDummyExpFromType(ty); | |
| 6608 | 23 | ety := Expression.typeof(exp); | |
| 6609 | 23 | ety := Expression.liftArrayLeft(ety, dim); | |
| 6610 | 23 | expl := List.fill(exp, idim); | |
| 6611 | 23 | then | |
| 6612 | DAE.ARRAY(ety, true, expl); | ||
| 6613 | |||
| 6614 | end match; | ||
| 6615 | end makeDummyExpFromType; | ||
| 6616 | |||
| 6617 | public function printExpTypeStr | ||
| 6618 | input DAE.Type iet; | ||
| 6619 | output String str; | ||
| 6620 | algorithm | ||
| 6621 | ✗ | str := TypesDump.printTypeStr(expTypetoTypesType(iet)); | |
| 6622 | end printExpTypeStr; | ||
| 6623 | |||
| 6624 | public function isUnknownType | ||
| 6625 | "Return true if the type is DAE.T_UNKNOWN or DAE.T_ANYTYPE" | ||
| 6626 | input DAE.Type inType; | ||
| 6627 | output Boolean b; | ||
| 6628 | algorithm | ||
| 6629 | b := match inType | ||
| 6630 | case DAE.T_UNKNOWN() then true; | ||
| 6631 | case DAE.T_ANYTYPE() then true; | ||
| 6632 | else false; | ||
| 6633 | end match; | ||
| 6634 | end isUnknownType; | ||
| 6635 | |||
| 6636 | public function isOverdeterminedType | ||
| 6637 | "Returns true if the given type is overdetermined, i.e. a type or record with | ||
| 6638 | an equalityConstraint function, otherwise false." | ||
| 6639 | input DAE.Type inType; | ||
| 6640 | output Boolean outIsOverdetermined; | ||
| 6641 | algorithm | ||
| 6642 | outIsOverdetermined := match inType | ||
| 6643 | local | ||
| 6644 | ClassInf.State cct; | ||
| 6645 | |||
| 6646 | case DAE.T_COMPLEX(complexClassType = cct, equalityConstraint = SOME(_)) | ||
| 6647 | ✗ | then ClassInfUtil.isTypeOrRecord(cct); | |
| 6648 | |||
| 6649 | case DAE.T_SUBTYPE_BASIC(equalityConstraint = SOME(_)) then true; | ||
| 6650 | end match; | ||
| 6651 | end isOverdeterminedType; | ||
| 6652 | |||
| 6653 | public function hasMetaArray | ||
| 6654 | input DAE.Type ty; | ||
| 6655 | output Boolean b; | ||
| 6656 | algorithm | ||
| 6657 | 38325 | (_,b) := traverseType(ty, false, hasMetaArrayWork); | |
| 6658 | end hasMetaArray; | ||
| 6659 | |||
| 6660 | protected function hasMetaArrayWork | ||
| 6661 | input Type ty; | ||
| 6662 | input Boolean b; | ||
| 6663 | output Type oty = ty; | ||
| 6664 | output Boolean ob = b; | ||
| 6665 | algorithm | ||
| 6666 |
1/2✓ Branch 0 taken 67511 times.
✗ Branch 1 not taken.
|
67511 | if not b then |
| 6667 | ob := match ty | ||
| 6668 | case DAE.T_METAARRAY() then true; | ||
| 6669 | else false; | ||
| 6670 | end match; | ||
| 6671 | end if; | ||
| 6672 | end hasMetaArrayWork; | ||
| 6673 | |||
| 6674 | protected function classTypeEqualIfRecord | ||
| 6675 | input ClassInf.State st1; | ||
| 6676 | input ClassInf.State st2; | ||
| 6677 | output Boolean b; | ||
| 6678 | algorithm | ||
| 6679 | b := match (st1,st2) | ||
| 6680 | local | ||
| 6681 | Absyn.Path p1,p2; | ||
| 6682 | 53210 | case (ClassInf.RECORD(p1),ClassInf.RECORD(p2)) then AbsynUtil.pathEqual(p1,p2); | |
| 6683 | else true; | ||
| 6684 | end match; | ||
| 6685 | end classTypeEqualIfRecord; | ||
| 6686 | |||
| 6687 | public function ifExpMakeDimsUnknown "If one branch of an if-expression has truly unknown dimensions they both will need to return unknown dimensions for type-checking to work" | ||
| 6688 | input DAE.Type ty1; | ||
| 6689 | input DAE.Type ty2; | ||
| 6690 | output DAE.Type oty1; | ||
| 6691 | output DAE.Type oty2; | ||
| 6692 | algorithm | ||
| 6693 | (oty1,oty2) := match (ty1,ty2) | ||
| 6694 | local | ||
| 6695 | DAE.Type inner1,inner2; | ||
| 6696 | DAE.Dimension d1,d2; | ||
| 6697 | case (DAE.T_ARRAY(ty=inner1,dims={DAE.DIM_UNKNOWN()}),DAE.T_ARRAY(ty=inner2,dims={_})) | ||
| 6698 | algorithm | ||
| 6699 | ✗ | (oty1,oty2) := ifExpMakeDimsUnknown(inner1,inner2); | |
| 6700 | ✗ | then (DAE.T_ARRAY(inner1,DAE.DIM_UNKNOWN()::{}),DAE.T_ARRAY(inner2,DAE.DIM_UNKNOWN()::{})); | |
| 6701 | case (DAE.T_ARRAY(ty=inner1,dims={_}),DAE.T_ARRAY(ty=inner2,dims={DAE.DIM_UNKNOWN()})) | ||
| 6702 | algorithm | ||
| 6703 | ✗ | (oty1,oty2) := ifExpMakeDimsUnknown(inner1,inner2); | |
| 6704 | ✗ | then (DAE.T_ARRAY(inner1,DAE.DIM_UNKNOWN()::{}),DAE.T_ARRAY(inner2,DAE.DIM_UNKNOWN()::{})); | |
| 6705 | case (DAE.T_ARRAY(ty=inner1,dims={d1}),DAE.T_ARRAY(ty=inner2,dims={d2})) | ||
| 6706 | algorithm | ||
| 6707 | ✗ | (oty1,oty2) := ifExpMakeDimsUnknown(inner1,inner2); | |
| 6708 | ✗ | then (DAE.T_ARRAY(inner1,{d1}),DAE.T_ARRAY(inner2,{d2})); | |
| 6709 | else (ty1,ty2); | ||
| 6710 | end match; | ||
| 6711 | end ifExpMakeDimsUnknown; | ||
| 6712 | |||
| 6713 | public function isFixedWithNoBinding | ||
| 6714 | "check if the type has bindings for everything | ||
| 6715 | if is parameter or constant without fixed = false | ||
| 6716 | specified otherwise" | ||
| 6717 | input DAE.Type inTy; | ||
| 6718 | input SCode.Variability inVariability; | ||
| 6719 | output Boolean outFixed; | ||
| 6720 | algorithm | ||
| 6721 | outFixed := matchcontinue inTy | ||
| 6722 | local | ||
| 6723 | Boolean b; | ||
| 6724 | list<DAE.Var> vl; | ||
| 6725 | |||
| 6726 | case _ | ||
| 6727 | algorithm | ||
| 6728 | // if this function doesn't fail return its value | ||
| 6729 | ✗ | b := getFixedVarAttribute(inTy); | |
| 6730 | then | ||
| 6731 | b; | ||
| 6732 | |||
| 6733 | case DAE.T_COMPLEX(varLst = vl) | ||
| 6734 | algorithm | ||
| 6735 | ✗ | true := allHaveBindings(vl); | |
| 6736 | then | ||
| 6737 | false; | ||
| 6738 | |||
| 6739 | // we couldn't get the fixed attribute | ||
| 6740 | // assume true for constants and parameters | ||
| 6741 | // false otherwise | ||
| 6742 | else | ||
| 6743 | algorithm | ||
| 6744 | ✗ | b := listMember(inVariability, {SCode.PARAM(), SCode.CONST()}); | |
| 6745 | then | ||
| 6746 | b; | ||
| 6747 | |||
| 6748 | end matchcontinue; | ||
| 6749 | end isFixedWithNoBinding; | ||
| 6750 | |||
| 6751 | public function allHaveBindings | ||
| 6752 | input list<DAE.Var> inVars; | ||
| 6753 | output Boolean b; | ||
| 6754 | algorithm | ||
| 6755 | b := match inVars | ||
| 6756 | local | ||
| 6757 | DAE.Var v; | ||
| 6758 | list<DAE.Var> rest; | ||
| 6759 | |||
| 6760 | case {} then true; | ||
| 6761 | |||
| 6762 | case v::_ guard not hasBinding(v) | ||
| 6763 | then | ||
| 6764 | false; | ||
| 6765 | |||
| 6766 | case v::rest | ||
| 6767 | algorithm | ||
| 6768 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7059 times.
|
7059 | true := hasBinding(v); |
| 6769 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7059 times.
|
7059 | true := allHaveBindings(rest); |
| 6770 | then | ||
| 6771 | true; | ||
| 6772 | |||
| 6773 | end match; | ||
| 6774 | end allHaveBindings; | ||
| 6775 | |||
| 6776 | public function hasBinding | ||
| 6777 | input DAE.Var inVar; | ||
| 6778 | output Boolean b; | ||
| 6779 | algorithm | ||
| 6780 | b := match inVar | ||
| 6781 | case DAE.TYPES_VAR(binding = DAE.UNBOUND()) then false; | ||
| 6782 | else true; | ||
| 6783 | end match; | ||
| 6784 | end hasBinding; | ||
| 6785 | |||
| 6786 | public function typeErrorSanityCheck | ||
| 6787 | input String inType1; | ||
| 6788 | input String inType2; | ||
| 6789 | input SourceInfo inInfo; | ||
| 6790 | algorithm | ||
| 6791 |
3/4✓ Branch 0 taken 1 time.
✓ Branch 1 taken 18203 times.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
|
18204 | if stringEq(inType1, inType2) then |
| 6792 | ✗ | Error.addSourceMessage(Error.ERRONEOUS_TYPE_ERROR, {inType1}, inInfo); | |
| 6793 | ✗ | fail(); | |
| 6794 | end if; | ||
| 6795 | end typeErrorSanityCheck; | ||
| 6796 | |||
| 6797 | public function dimNotFixed | ||
| 6798 | input DAE.Dimension dim; | ||
| 6799 | output Boolean b; | ||
| 6800 | algorithm | ||
| 6801 | b := match dim | ||
| 6802 | case DAE.DIM_UNKNOWN() then true; | ||
| 6803 | case DAE.DIM_EXP() then true; | ||
| 6804 | else false; | ||
| 6805 | end match; | ||
| 6806 | end dimNotFixed; | ||
| 6807 | |||
| 6808 | function isArrayWithUnknownDimension | ||
| 6809 | input DAE.Type ty; | ||
| 6810 | output Boolean b; | ||
| 6811 | algorithm | ||
| 6812 | b := match ty | ||
| 6813 |
4/4✓ Branch 1 taken 72 times.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 72 times.
✓ Branch 4 taken 61 times.
|
133 | case DAE.T_ARRAY() then max( |
| 6814 | match d case DAE.DIM_UNKNOWN() then true; else false; end match | ||
| 6815 | for d in TypesDump.getDimensions(ty)); | ||
| 6816 | else false; | ||
| 6817 | end match; | ||
| 6818 | end isArrayWithUnknownDimension; | ||
| 6819 | |||
| 6820 | public function setTypeVars | ||
| 6821 | input output DAE.Type ty; | ||
| 6822 | input list<DAE.Var> inVars; | ||
| 6823 | algorithm | ||
| 6824 | ty := match ty | ||
| 6825 | case DAE.T_REAL() | ||
| 6826 | algorithm | ||
| 6827 | 383227 | ty.varLst := inVars; | |
| 6828 | then ty; | ||
| 6829 | case DAE.T_INTEGER() | ||
| 6830 | algorithm | ||
| 6831 | 14549 | ty.varLst := inVars; | |
| 6832 | then ty; | ||
| 6833 | case DAE.T_STRING() | ||
| 6834 | algorithm | ||
| 6835 | 27957 | ty.varLst := inVars; | |
| 6836 | then ty; | ||
| 6837 | case DAE.T_BOOL() | ||
| 6838 | algorithm | ||
| 6839 | 29796 | ty.varLst := inVars; | |
| 6840 | then ty; | ||
| 6841 | case DAE.T_CLOCK() | ||
| 6842 | algorithm | ||
| 6843 | 26 | ty.varLst := inVars; | |
| 6844 | then ty; | ||
| 6845 | case DAE.T_ENUMERATION() | ||
| 6846 | algorithm | ||
| 6847 | ✗ | ty.attributeLst := inVars; | |
| 6848 | then ty; | ||
| 6849 | case DAE.T_ARRAY() | ||
| 6850 | algorithm | ||
| 6851 | ✗ | ty.ty := setTypeVars(ty.ty, inVars); | |
| 6852 | then ty; | ||
| 6853 | case DAE.T_SUBTYPE_BASIC() | ||
| 6854 | algorithm | ||
| 6855 | ✗ | ty.complexType := setTypeVars(ty.complexType, inVars); | |
| 6856 | then ty; | ||
| 6857 | end match; | ||
| 6858 | end setTypeVars; | ||
| 6859 | |||
| 6860 | public function isEmptyOrNoRetcall | ||
| 6861 | input DAE.Type ty; | ||
| 6862 | output Boolean b; | ||
| 6863 | algorithm | ||
| 6864 | b := match ty | ||
| 6865 | case DAE.T_TUPLE(types={}) then true; | ||
| 6866 | case DAE.T_METATUPLE(types={}) then true; | ||
| 6867 | case DAE.T_NORETCALL() then true; | ||
| 6868 | else false; | ||
| 6869 | end match; | ||
| 6870 | end isEmptyOrNoRetcall; | ||
| 6871 | |||
| 6872 | protected function typeConvertIntToEnumCheck " | ||
| 6873 | Deal with the invalid conversions from Integer to enumeration. | ||
| 6874 | If the Integer corresponds to the Integer(ENUM) value of some enumeration constant ENUM, | ||
| 6875 | just give a warning, otherwise report an error. | ||
| 6876 | Returns false if an error was reported, otherwise true. | ||
| 6877 | " | ||
| 6878 | input DAE.Exp exp; | ||
| 6879 | input DAE.Type expected; | ||
| 6880 | output Boolean conversionOK; | ||
| 6881 | algorithm | ||
| 6882 | conversionOK := matchcontinue (exp, expected) | ||
| 6883 | local | ||
| 6884 | Integer oi; | ||
| 6885 | Absyn.Path tp; | ||
| 6886 | list<String> l; | ||
| 6887 | String pathStr, intStr, enumConst, lengthStr; | ||
| 6888 | case (DAE.ICONST(oi), | ||
| 6889 | DAE.T_ENUMERATION(path = tp, names = l)) | ||
| 6890 | algorithm | ||
| 6891 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
|
7 | true := (1 <= oi and oi <= listLength(l)); |
| 6892 | 7 | pathStr := AbsynUtil.pathString(tp); | |
| 6893 | 7 | intStr := intString(oi); | |
| 6894 | 7 | enumConst := listGet(l, oi); | |
| 6895 | 7 | Error.addMessage(Error.INTEGER_ENUMERATION_CONVERSION_WARNING, {intStr, pathStr, enumConst}); | |
| 6896 | then true; | ||
| 6897 | case (DAE.ICONST(oi), | ||
| 6898 | DAE.T_ENUMERATION(path = tp, names = l)) | ||
| 6899 | algorithm | ||
| 6900 | ✗ | pathStr := AbsynUtil.pathString(tp); | |
| 6901 | ✗ | false := stringEq(pathStr, ""); | |
| 6902 | ✗ | intStr := intString(oi); | |
| 6903 | ✗ | lengthStr := intString(listLength(l)); | |
| 6904 | ✗ | Error.addMessage(Error.INTEGER_ENUMERATION_OUT_OF_RANGE, {pathStr, intStr, lengthStr}); | |
| 6905 | then false; | ||
| 6906 | case (DAE.ICONST(oi), | ||
| 6907 | DAE.T_ENUMERATION(path = tp)) | ||
| 6908 | algorithm | ||
| 6909 | ✗ | pathStr := AbsynUtil.pathString(tp); | |
| 6910 | ✗ | true := stringEq(pathStr, ""); | |
| 6911 | ✗ | intStr := intString(oi); | |
| 6912 | ✗ | Error.addMessage(Error.INTEGER_TO_UNKNOWN_ENUMERATION, {intStr}); | |
| 6913 | then false; | ||
| 6914 | end matchcontinue; | ||
| 6915 | end typeConvertIntToEnumCheck; | ||
| 6916 | |||
| 6917 | public function findVarIndex | ||
| 6918 | input String id; | ||
| 6919 | input list<DAE.Var> vars; | ||
| 6920 | output Integer index; | ||
| 6921 | algorithm | ||
| 6922 | 2253 | index := List.position1OnTrue(vars,selectVar,id)-1 "shift to zero-based index"; | |
| 6923 | end findVarIndex; | ||
| 6924 | |||
| 6925 | protected function selectVar | ||
| 6926 | input DAE.Var var; | ||
| 6927 | input String id; | ||
| 6928 | output Boolean b; | ||
| 6929 | algorithm | ||
| 6930 | b := match var | ||
| 6931 | local | ||
| 6932 | String id1; | ||
| 6933 |
4/4✓ Branch 0 taken 2554 times.
✓ Branch 1 taken 2104 times.
✓ Branch 3 taken 301 times.
✓ Branch 4 taken 2253 times.
|
4658 | case DAE.TYPES_VAR(name=id1) then stringEq(id,id1); |
| 6934 | else false; | ||
| 6935 | end match; | ||
| 6936 | end selectVar; | ||
| 6937 | |||
| 6938 | public function getUniontypeIfMetarecord | ||
| 6939 | input DAE.Type inTy; | ||
| 6940 | output DAE.Type ty; | ||
| 6941 | algorithm | ||
| 6942 | ty := match inTy | ||
| 6943 | local | ||
| 6944 | Boolean b; | ||
| 6945 | Absyn.Path p; | ||
| 6946 | ✗ | case DAE.T_METARECORD(utPath=p,knownSingleton=b) then DAE.T_METAUNIONTYPE({},inTy.typeVars,b,if b then DAE.EVAL_SINGLETON_KNOWN_TYPE(inTy) else DAE.NOT_SINGLETON(),p); | |
| 6947 | else inTy; | ||
| 6948 | end match; | ||
| 6949 | end getUniontypeIfMetarecord; | ||
| 6950 | |||
| 6951 | public function getUniontypeIfMetarecordReplaceAllSubtypes | ||
| 6952 | input DAE.Type inTy; | ||
| 6953 | output DAE.Type ty; | ||
| 6954 | algorithm | ||
| 6955 | 269744 | (ty,_) := traverseType(inTy, 1, getUniontypeIfMetarecordTraverse); | |
| 6956 | end getUniontypeIfMetarecordReplaceAllSubtypes; | ||
| 6957 | |||
| 6958 | protected function getUniontypeIfMetarecordTraverse | ||
| 6959 | input DAE.Type ty; | ||
| 6960 | input Integer dummy; | ||
| 6961 | output DAE.Type oty; | ||
| 6962 | output Integer odummy = dummy; | ||
| 6963 | algorithm | ||
| 6964 | oty := match ty | ||
| 6965 |
2/2✓ Branch 0 taken 611 times.
✓ Branch 1 taken 17279 times.
|
17890 | case DAE.T_METARECORD() then DAE.T_METAUNIONTYPE({},ty.typeVars,ty.knownSingleton,if ty.knownSingleton then DAE.EVAL_SINGLETON_KNOWN_TYPE(ty) else DAE.NOT_SINGLETON(),ty.utPath); |
| 6966 | else ty; | ||
| 6967 | end match; | ||
| 6968 | end getUniontypeIfMetarecordTraverse; | ||
| 6969 | |||
| 6970 | protected function isBuiltin | ||
| 6971 | input DAE.FunctionBuiltin a; | ||
| 6972 | output Boolean b; | ||
| 6973 | algorithm | ||
| 6974 | b := match a | ||
| 6975 | case DAE.FUNCTION_NOT_BUILTIN() then false; | ||
| 6976 | else true; | ||
| 6977 | end match; | ||
| 6978 | end isBuiltin; | ||
| 6979 | |||
| 6980 | public function makeCallAttr | ||
| 6981 | input DAE.Type ty; | ||
| 6982 | input DAE.FunctionAttributes attr; | ||
| 6983 | output DAE.CallAttributes callAttr; | ||
| 6984 | protected | ||
| 6985 | Boolean isImpure,isT,isB; | ||
| 6986 | algorithm | ||
| 6987 | 165 | isT := isTuple(ty); | |
| 6988 | 165 | isB := isBuiltin(attr.isBuiltin); | |
| 6989 | 165 | isImpure := attr.purity == DAE.Purity.IMPURE; | |
| 6990 |
3/6✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 165 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 165 times.
✗ Branch 5 not taken.
|
660 | callAttr := DAE.CALL_ATTR(ty,isT,isB,isImpure,false,attr.inline,DAE.NO_TAIL(),DAE.NoReturn.RETURNS); |
| 6991 | end makeCallAttr; | ||
| 6992 | |||
| 6993 | public function builtinName | ||
| 6994 | input DAE.FunctionBuiltin isbuiltin; | ||
| 6995 | output Option<String> name; | ||
| 6996 | algorithm | ||
| 6997 | ✗ | name := match isbuiltin case DAE.FUNCTION_BUILTIN() then isbuiltin.name; else NONE(); end match; | |
| 6998 | end builtinName; | ||
| 6999 | |||
| 7000 | public function getFuncArg | ||
| 7001 | input DAE.Type ty; | ||
| 7002 | output list<DAE.FuncArg> args; | ||
| 7003 | algorithm | ||
| 7004 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | DAE.T_FUNCTION(funcArg=args) := ty; |
| 7005 | end getFuncArg; | ||
| 7006 | |||
| 7007 | public function isArray1D | ||
| 7008 | input DAE.Type inType; | ||
| 7009 | output Boolean b; | ||
| 7010 | algorithm | ||
| 7011 | b := match inType | ||
| 7012 | local | ||
| 7013 | DAE.Type ty; | ||
| 7014 | ✗ | case DAE.T_ARRAY(ty = ty) then not arrayType(ty); | |
| 7015 | else false; | ||
| 7016 | end match; | ||
| 7017 | end isArray1D; | ||
| 7018 | |||
| 7019 | public function isArray2D | ||
| 7020 | input DAE.Type inType; | ||
| 7021 | output Boolean b; | ||
| 7022 | algorithm | ||
| 7023 | b := match inType | ||
| 7024 | local | ||
| 7025 | DAE.Type ty; | ||
| 7026 | ✗ | case DAE.T_ARRAY(ty = DAE.T_ARRAY(ty = ty)) then not arrayType(ty); | |
| 7027 | else false; | ||
| 7028 | end match; | ||
| 7029 | end isArray2D; | ||
| 7030 | |||
| 7031 | public function funcArgName | ||
| 7032 | input DAE.FuncArg arg; | ||
| 7033 | output String name; | ||
| 7034 | algorithm | ||
| 7035 | ✗ | DAE.FUNCARG(name=name) := arg; | |
| 7036 | end funcArgName; | ||
| 7037 | |||
| 7038 | public function funcArgType | ||
| 7039 | input DAE.FuncArg arg; | ||
| 7040 | output DAE.Type ty; | ||
| 7041 | algorithm | ||
| 7042 | 385333 | DAE.FUNCARG(ty=ty) := arg; | |
| 7043 | end funcArgType; | ||
| 7044 | |||
| 7045 | public function funcArgDefaultBinding | ||
| 7046 | input DAE.FuncArg arg; | ||
| 7047 | output Option<DAE.Exp> defaultBinding; | ||
| 7048 | algorithm | ||
| 7049 | 12 | DAE.FUNCARG(defaultBinding=defaultBinding) := arg; | |
| 7050 | end funcArgDefaultBinding; | ||
| 7051 | |||
| 7052 | public function setFuncArgType | ||
| 7053 | input DAE.FuncArg arg; | ||
| 7054 | input DAE.Type ty; | ||
| 7055 | output DAE.FuncArg outArg; | ||
| 7056 | protected | ||
| 7057 | String name; | ||
| 7058 | DAE.Const const; | ||
| 7059 | DAE.VarParallelism par; | ||
| 7060 | Option<DAE.Exp> defaultBinding; | ||
| 7061 | algorithm | ||
| 7062 | 203770 | DAE.FUNCARG(name,_,const,par,defaultBinding) := arg; | |
| 7063 | 203770 | outArg := DAE.FUNCARG(name,ty,const,par,defaultBinding); | |
| 7064 | end setFuncArgType; | ||
| 7065 | |||
| 7066 | public function setFuncArgName | ||
| 7067 | input DAE.FuncArg arg; | ||
| 7068 | input String name; | ||
| 7069 | output DAE.FuncArg outArg; | ||
| 7070 | protected | ||
| 7071 | DAE.Type ty; | ||
| 7072 | DAE.Const const; | ||
| 7073 | DAE.VarParallelism par; | ||
| 7074 | Option<DAE.Exp> defaultBinding; | ||
| 7075 | algorithm | ||
| 7076 | 168 | DAE.FUNCARG(_,ty,const,par,defaultBinding) := arg; | |
| 7077 | 168 | outArg := DAE.FUNCARG(name,ty,const,par,defaultBinding); | |
| 7078 | end setFuncArgName; | ||
| 7079 | |||
| 7080 | public function clearDefaultBinding | ||
| 7081 | input DAE.FuncArg arg; | ||
| 7082 | output DAE.FuncArg outArg; | ||
| 7083 | protected | ||
| 7084 | String name; | ||
| 7085 | DAE.Type ty; | ||
| 7086 | DAE.Const const; | ||
| 7087 | DAE.VarParallelism par; | ||
| 7088 | algorithm | ||
| 7089 | 6 | DAE.FUNCARG(name,ty,const,par,_) := arg; | |
| 7090 | 6 | outArg := DAE.FUNCARG(name,ty,const,par,NONE()); | |
| 7091 | end clearDefaultBinding; | ||
| 7092 | |||
| 7093 | public function makeDefaultFuncArg | ||
| 7094 | input String name; | ||
| 7095 | input DAE.Type ty; | ||
| 7096 | output DAE.FuncArg arg; | ||
| 7097 | algorithm | ||
| 7098 | 38842 | arg := DAE.FUNCARG(name,ty,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()); | |
| 7099 | end makeDefaultFuncArg; | ||
| 7100 | |||
| 7101 | public function setIsFunctionPointer | ||
| 7102 | input DAE.Type ty; | ||
| 7103 | input Integer dummy; | ||
| 7104 | output DAE.Type oty = ty; | ||
| 7105 | output Integer odummy = dummy; | ||
| 7106 | algorithm | ||
| 7107 | oty := match oty | ||
| 7108 | local | ||
| 7109 | DAE.FunctionAttributes attr; | ||
| 7110 | case DAE.T_FUNCTION(functionAttributes=attr as DAE.FUNCTION_ATTRIBUTES(isFunctionPointer=false)) | ||
| 7111 | algorithm | ||
| 7112 | 704 | attr.isFunctionPointer := true; | |
| 7113 | 704 | oty.functionAttributes := attr; | |
| 7114 | then oty; | ||
| 7115 | else oty; | ||
| 7116 | end match; | ||
| 7117 | end setIsFunctionPointer; | ||
| 7118 | |||
| 7119 | public function isFunctionReferenceVar | ||
| 7120 | input DAE.Type ty; | ||
| 7121 | output Boolean b; | ||
| 7122 | algorithm | ||
| 7123 | b := match ty | ||
| 7124 | case DAE.T_FUNCTION_REFERENCE_VAR() then true; | ||
| 7125 | else false; | ||
| 7126 | end match; | ||
| 7127 | end isFunctionReferenceVar; | ||
| 7128 | |||
| 7129 | public function isFunctionPointer | ||
| 7130 | input DAE.Type inType; | ||
| 7131 | output Boolean outIsFunPtr; | ||
| 7132 | algorithm | ||
| 7133 | outIsFunPtr := match inType | ||
| 7134 | case DAE.T_FUNCTION(functionAttributes = | ||
| 7135 | DAE.FUNCTION_ATTRIBUTES(isFunctionPointer = true)) then true; | ||
| 7136 | else false; | ||
| 7137 | end match; | ||
| 7138 | end isFunctionPointer; | ||
| 7139 | |||
| 7140 | public function filterRecordComponents | ||
| 7141 | input list<DAE.Var> inRecordVars; | ||
| 7142 | input SourceInfo inInfo; | ||
| 7143 | output list<DAE.Var> outRecordVars; | ||
| 7144 | algorithm | ||
| 7145 |
4/4✓ Branch 0 taken 33658 times.
✓ Branch 1 taken 3514 times.
✓ Branch 2 taken 33658 times.
✓ Branch 3 taken 3514 times.
|
37172 | outRecordVars := list(match v case DAE.TYPES_VAR() |
| 7146 | algorithm | ||
| 7147 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 33658 times.
|
33658 | if not allowedInRecord(v.ty) then |
| 7148 | ✗ | Error.addSourceMessage(Error.ILLEGAL_RECORD_COMPONENT, {TypesDump.unparseVar(v)}, inInfo); | |
| 7149 | ✗ | fail(); | |
| 7150 | end if; | ||
| 7151 | then v; | ||
| 7152 | end match for v in inRecordVars | ||
| 7153 | ); | ||
| 7154 | end filterRecordComponents; | ||
| 7155 | |||
| 7156 | public function allowedInRecord | ||
| 7157 | input DAE.Type ty; | ||
| 7158 | output Boolean yes; | ||
| 7159 | algorithm | ||
| 7160 | yes := matchcontinue ty | ||
| 7161 | local DAE.Type t; | ||
| 7162 | |||
| 7163 | // basic types, records or arrays of the same | ||
| 7164 | case _ | ||
| 7165 | algorithm | ||
| 7166 | 33658 | t := arrayElementType(ty); | |
| 7167 |
3/6✓ Branch 1 taken 32 times.
✓ Branch 2 taken 33626 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 32 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
33658 | true := basicType(t) or isRecord(t) or extendsBasicType(t); |
| 7168 | then | ||
| 7169 | true; | ||
| 7170 | |||
| 7171 | // nothing else please! | ||
| 7172 | else false; | ||
| 7173 | |||
| 7174 | end matchcontinue; | ||
| 7175 | end allowedInRecord; | ||
| 7176 | |||
| 7177 | public function lookupIndexInMetaRecord | ||
| 7178 | input list<DAE.Var> vars; | ||
| 7179 | input String name; | ||
| 7180 | output Integer index; | ||
| 7181 | algorithm | ||
| 7182 | 29 | index := List.position1OnTrue(vars, DAEUtil.typeVarIdentEqual, name); | |
| 7183 | end lookupIndexInMetaRecord; | ||
| 7184 | |||
| 7185 | function checkEnumDuplicateLiterals | ||
| 7186 | input list<String> names; | ||
| 7187 | input Absyn.Info info; | ||
| 7188 | protected | ||
| 7189 | list<String> sortedNames; | ||
| 7190 | algorithm | ||
| 7191 | // Sort+uniq = O(n*log(n)); naive way to check duplicates is O(n*n) but might be faster... | ||
| 7192 | 4512 | sortedNames := List.sort(names,Util.strcmpBool); | |
| 7193 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4512 times.
|
4512 | if not List.sortedListAllUnique(sortedNames, stringEq) then |
| 7194 | ✗ | Error.addSourceMessage(Error.ENUM_DUPLICATES, {stringDelimitList(List.sortedUniqueOnlyDuplicates(sortedNames, stringEq), ","), stringDelimitList(names, ",")}, info); | |
| 7195 | ✗ | fail(); | |
| 7196 | end if; | ||
| 7197 | end checkEnumDuplicateLiterals; | ||
| 7198 | |||
| 7199 | public function checkTypeCompat | ||
| 7200 | "This function checks that two types are compatible, as per the definition of | ||
| 7201 | type compatible expressions in the specification. If needed it also does type | ||
| 7202 | casting to make the expressions compatible. If the types are compatible it | ||
| 7203 | returns the compatible type, otherwise the type returned is undefined." | ||
| 7204 | input DAE.Exp inExp1; | ||
| 7205 | input DAE.Type inType1; | ||
| 7206 | input DAE.Exp inExp2; | ||
| 7207 | input DAE.Type inType2; | ||
| 7208 | input Boolean inAllowUnknown = false; | ||
| 7209 | output DAE.Exp outExp1 = inExp1; | ||
| 7210 | output DAE.Exp outExp2 = inExp2; | ||
| 7211 | output DAE.Type outCompatType; | ||
| 7212 | output Boolean outCompatible = true; | ||
| 7213 | protected | ||
| 7214 | DAE.Type ty1, ty2; | ||
| 7215 | algorithm | ||
| 7216 | // Return true if the references are the same. | ||
| 7217 |
2/2✓ Branch 0 taken 1672 times.
✓ Branch 1 taken 8417 times.
|
10089 | if referenceEq(inType1, inType2) then |
| 7218 | 1672 | outCompatType := inType1; | |
| 7219 | 1672 | return; | |
| 7220 | end if; | ||
| 7221 | |||
| 7222 | // Check if the types are different kinds of types. | ||
| 7223 |
2/2✓ Branch 0 taken 822 times.
✓ Branch 1 taken 7595 times.
|
8417 | if valueConstructor(inType1) <> valueConstructor(inType2) then |
| 7224 |
3/4✓ Branch 1 taken 822 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 821 times.
|
822 | if extendsBasicType(inType1) or extendsBasicType(inType2) then |
| 7225 | // If either type extends a basic type, check the basic type instead. | ||
| 7226 | 1 | ty1 := derivedBasicType(inType1); | |
| 7227 | 1 | ty2 := derivedBasicType(inType2); | |
| 7228 | 1 | (outExp1, outExp2, outCompatType, outCompatible) := | |
| 7229 | checkTypeCompat(inExp1, ty1, inExp2, ty2); | ||
| 7230 | else | ||
| 7231 | // If the types are not of the same kind they might need to be type cast | ||
| 7232 | // to become compatible. | ||
| 7233 | 821 | (outExp1, outExp2, outCompatType, outCompatible) := | |
| 7234 | checkTypeCompat_cast(inExp1, inType1, inExp2, inType2, inAllowUnknown); | ||
| 7235 | end if; | ||
| 7236 | |||
| 7237 | // Regardless of the chosen branch above, we are done here. | ||
| 7238 | 822 | return; | |
| 7239 | end if; | ||
| 7240 | |||
| 7241 | // The types are of the same kind, so we only need to match on one of them | ||
| 7242 | // (which is a lot more efficient than matching both). | ||
| 7243 | outCompatType := match inType1 | ||
| 7244 | local | ||
| 7245 | list<DAE.Dimension> dims1, dims2; | ||
| 7246 | DAE.Type ety1, ety2, ty; | ||
| 7247 | list<String> names; | ||
| 7248 | list<DAE.Var> vars; | ||
| 7249 | list<FuncArg> args; | ||
| 7250 | list<DAE.Type> tys, tys2; | ||
| 7251 | String name; | ||
| 7252 | Absyn.Path p1, p2; | ||
| 7253 | |||
| 7254 | // Basic types, must be the same. | ||
| 7255 | case DAE.T_INTEGER() then DAE.T_INTEGER_DEFAULT; | ||
| 7256 | case DAE.T_REAL() then DAE.T_REAL_DEFAULT; | ||
| 7257 | case DAE.T_STRING() then DAE.T_STRING_DEFAULT; | ||
| 7258 | case DAE.T_BOOL() then DAE.T_BOOL_DEFAULT; | ||
| 7259 | case DAE.T_CLOCK() then DAE.T_CLOCK_DEFAULT; | ||
| 7260 | |||
| 7261 | case DAE.T_SUBTYPE_BASIC() | ||
| 7262 | algorithm | ||
| 7263 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | DAE.T_SUBTYPE_BASIC(complexType = ty) := inType2; |
| 7264 | 2 | (outExp1, outExp2, outCompatType, outCompatible) := | |
| 7265 | checkTypeCompat(inExp1, inType1.complexType, inExp2, ty); | ||
| 7266 | 2 | then | |
| 7267 | outCompatType; | ||
| 7268 | |||
| 7269 | // Enumerations, check that they have same literals. | ||
| 7270 | case DAE.T_ENUMERATION() | ||
| 7271 | algorithm | ||
| 7272 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2276 times.
|
2276 | DAE.T_ENUMERATION(names = names) := inType2; |
| 7273 | 2276 | outCompatible := List.isEqualOnTrue(inType1.names, names, stringEq); | |
| 7274 | then | ||
| 7275 | inType1; | ||
| 7276 | |||
| 7277 | // Arrays, must have compatible element types and dimensions. | ||
| 7278 | case DAE.T_ARRAY() | ||
| 7279 | algorithm | ||
| 7280 | // Check that the element types are compatible. | ||
| 7281 | 647 | ety1 := arrayElementType(inType1); | |
| 7282 | 647 | ety2 := arrayElementType(inType2); | |
| 7283 | 647 | (outExp1, outExp2, outCompatType, outCompatible) := | |
| 7284 | checkTypeCompat(inExp1, ety1, inExp2, ety2); | ||
| 7285 | |||
| 7286 | // If the element types are compatible, check the dimensions too. | ||
| 7287 |
1/2✓ Branch 0 taken 647 times.
✗ Branch 1 not taken.
|
647 | if outCompatible then |
| 7288 | 647 | dims1 := TypesDump.getDimensions(inType1); | |
| 7289 | 647 | dims2 := TypesDump.getDimensions(inType2); | |
| 7290 | |||
| 7291 | // The arrays must have the same number of dimensions. | ||
| 7292 |
1/2✓ Branch 2 taken 647 times.
✗ Branch 3 not taken.
|
647 | if listLength(dims1) == listLength(dims2) then |
| 7293 |
9/10✓ Branch 0 taken 686 times.
✓ Branch 1 taken 647 times.
✓ Branch 2 taken 686 times.
✓ Branch 3 taken 647 times.
✓ Branch 4 taken 686 times.
✓ Branch 5 taken 647 times.
✓ Branch 7 taken 10 times.
✓ Branch 8 taken 676 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 647 times.
|
1333 | dims1 := list(if Expression.dimensionsKnownAndEqual(dim1, dim2) then |
| 7294 | dim1 else DAE.DIM_UNKNOWN() threaded for dim1 in dims1, dim2 in dims2); | ||
| 7295 | 647 | outCompatType := liftArrayListDims(outCompatType, dims1); | |
| 7296 | else | ||
| 7297 | ✗ | outCompatible := false; | |
| 7298 | end if; | ||
| 7299 | end if; | ||
| 7300 | 647 | then | |
| 7301 | outCompatType; | ||
| 7302 | |||
| 7303 | // Records, must have the same components. | ||
| 7304 | case DAE.T_COMPLEX(complexClassType = ClassInf.RECORD()) | ||
| 7305 | algorithm | ||
| 7306 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
|
91 | DAE.T_COMPLEX(varLst = vars) := inType2; |
| 7307 | // TODO: Implement type casting for records with the same components but | ||
| 7308 | // in different order. | ||
| 7309 | 91 | outCompatible := List.isEqualOnTrue(inType1.varLst, vars, varEqualName); | |
| 7310 | then | ||
| 7311 | inType1; | ||
| 7312 | |||
| 7313 | case DAE.T_FUNCTION() | ||
| 7314 | algorithm | ||
| 7315 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | DAE.T_FUNCTION(funcResultType = ty, funcArg = args) := inType2; |
| 7316 | 2 | (outExp1, outExp2, outCompatType, outCompatible) := | |
| 7317 | checkTypeCompat(inExp1, inType1.funcResultType, inExp2, ty); | ||
| 7318 | |||
| 7319 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if outCompatible then |
| 7320 |
4/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
|
6 | tys := list(funcArgType(arg) for arg in inType1.funcArg); |
| 7321 |
4/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
|
6 | tys2 := list(funcArgType(arg) for arg in args); |
| 7322 | 2 | (_, outCompatible) := checkTypeCompatList(inExp1, tys, inExp2, tys2); | |
| 7323 | end if; | ||
| 7324 | then | ||
| 7325 | inType1; | ||
| 7326 | |||
| 7327 | case DAE.T_TUPLE() | ||
| 7328 | algorithm | ||
| 7329 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | DAE.T_TUPLE(types = tys) := inType2; |
| 7330 | 2 | (tys, outCompatible) := | |
| 7331 | checkTypeCompatList(inExp1, inType1.types, inExp2, tys); | ||
| 7332 | 2 | then | |
| 7333 | DAE.T_TUPLE(tys, inType1.names); | ||
| 7334 | |||
| 7335 | // MetaModelica types. | ||
| 7336 | case DAE.T_METALIST() | ||
| 7337 | algorithm | ||
| 7338 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
|
49 | DAE.T_METALIST(ty = ty) := inType2; |
| 7339 | //print("List(" + anyString(inType1.ty) + "), List(" + anyString(ty) + ")\n"); | ||
| 7340 | 49 | (outExp1, outExp2, outCompatType, outCompatible) := | |
| 7341 | checkTypeCompat(inExp1, inType1.ty, inExp2, ty, true); | ||
| 7342 | 49 | then DAE.T_METALIST(outCompatType); | |
| 7343 | |||
| 7344 | case DAE.T_METAARRAY() | ||
| 7345 | algorithm | ||
| 7346 | ✗ | DAE.T_METAARRAY(ty = ty) := inType2; | |
| 7347 | ✗ | (outExp1, outExp2, outCompatType, outCompatible) := | |
| 7348 | checkTypeCompat(inExp1, inType1.ty, inExp2, ty, true); | ||
| 7349 | ✗ | then DAE.T_METAARRAY(outCompatType); | |
| 7350 | |||
| 7351 | case DAE.T_METAOPTION() | ||
| 7352 | algorithm | ||
| 7353 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | DAE.T_METAOPTION(ty = ty) := inType2; |
| 7354 | 8 | (outExp1, outExp2, outCompatType, outCompatible) := | |
| 7355 | checkTypeCompat(inExp1, inType1.ty, inExp2, ty, true); | ||
| 7356 | 8 | then DAE.T_METAOPTION(outCompatType); | |
| 7357 | |||
| 7358 | case DAE.T_METATUPLE() | ||
| 7359 | algorithm | ||
| 7360 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | DAE.T_METATUPLE(types = tys) := inType2; |
| 7361 | 16 | (tys, outCompatible) := | |
| 7362 | checkTypeCompatList(inExp1, inType1.types, inExp2, tys); | ||
| 7363 | 16 | then DAE.T_METATUPLE(tys); | |
| 7364 | |||
| 7365 | case DAE.T_METABOXED() | ||
| 7366 | algorithm | ||
| 7367 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | DAE.T_METABOXED(ty = ty) := inType2; |
| 7368 | 14 | (outExp1, outExp2, outCompatType, outCompatible) := | |
| 7369 | checkTypeCompat(inExp1, inType1.ty, inExp2, ty); | ||
| 7370 | 14 | then DAE.T_METABOXED(outCompatType); | |
| 7371 | |||
| 7372 | case DAE.T_METAPOLYMORPHIC() | ||
| 7373 | algorithm | ||
| 7374 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | DAE.T_METAPOLYMORPHIC(name = name) := inType2; |
| 7375 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
|
6 | outCompatible := inType1.name == name; |
| 7376 | then inType1; | ||
| 7377 | |||
| 7378 | case DAE.T_METAUNIONTYPE(path = p1) | ||
| 7379 | algorithm | ||
| 7380 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | DAE.T_METAUNIONTYPE(path = p2) := inType2; |
| 7381 | 23 | outCompatible := AbsynUtil.pathEqual(p1, p2); | |
| 7382 | then inType1; | ||
| 7383 | |||
| 7384 | case DAE.T_METARECORD(utPath = p1) | ||
| 7385 | algorithm | ||
| 7386 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
|
137 | DAE.T_METARECORD(utPath = p2) := inType2; |
| 7387 | 137 | outCompatible := AbsynUtil.pathEqual(p1, p2); | |
| 7388 | then | ||
| 7389 | inType1; | ||
| 7390 | |||
| 7391 | case DAE.T_FUNCTION_REFERENCE_VAR() | ||
| 7392 | algorithm | ||
| 7393 | ✗ | DAE.T_FUNCTION_REFERENCE_VAR(functionType = ty) := inType2; | |
| 7394 | ✗ | (outExp1, outExp2, outCompatType, outCompatible) := | |
| 7395 | checkTypeCompat(inExp1, inType1.functionType, inExp2, ty); | ||
| 7396 | ✗ | then | |
| 7397 | DAE.T_FUNCTION_REFERENCE_VAR(outCompatType); | ||
| 7398 | |||
| 7399 | else | ||
| 7400 | algorithm | ||
| 7401 | ✗ | outCompatible := false; | |
| 7402 | then | ||
| 7403 | DAE.T_UNKNOWN_DEFAULT; | ||
| 7404 | |||
| 7405 | end match; | ||
| 7406 | end checkTypeCompat; | ||
| 7407 | |||
| 7408 | protected function checkTypeCompatList | ||
| 7409 | "Checks that two lists of types are compatible using checkTypeCompat." | ||
| 7410 | input DAE.Exp inExp1; | ||
| 7411 | input list<DAE.Type> inTypes1; | ||
| 7412 | input DAE.Exp inExp2; | ||
| 7413 | input list<DAE.Type> inTypes2; | ||
| 7414 | output list<DAE.Type> outCompatibleTypes = {}; | ||
| 7415 | output Boolean outCompatible = true; | ||
| 7416 | protected | ||
| 7417 | DAE.Type ty2; | ||
| 7418 | list<DAE.Type> rest_ty2 = inTypes2; | ||
| 7419 | Boolean compat; | ||
| 7420 | algorithm | ||
| 7421 |
1/2✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
20 | if listLength(inTypes1) <> listLength(inTypes2) then |
| 7422 | outCompatible := false; | ||
| 7423 | ✗ | return; | |
| 7424 | end if; | ||
| 7425 | |||
| 7426 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 20 times.
|
61 | for ty1 in inTypes1 loop |
| 7427 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | ty2 :: rest_ty2 := rest_ty2; |
| 7428 | // Ignore the returned expressions. This function is used for tuples, and | ||
| 7429 | // it's not clear how tuples should be type converted. So we only check that | ||
| 7430 | // the types are compatible and hope for the best. | ||
| 7431 | 41 | (_, _, ty2, compat) := checkTypeCompat(inExp1, ty1, inExp2, ty2); | |
| 7432 | |||
| 7433 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | if not compat then |
| 7434 | outCompatible := false; | ||
| 7435 | ✗ | return; | |
| 7436 | end if; | ||
| 7437 | |||
| 7438 | 41 | outCompatibleTypes := ty2 :: outCompatibleTypes; | |
| 7439 | end for; | ||
| 7440 | |||
| 7441 | 20 | outCompatibleTypes := listReverse(outCompatibleTypes); | |
| 7442 | end checkTypeCompatList; | ||
| 7443 | |||
| 7444 | protected function checkTypeCompat_cast | ||
| 7445 | "Helper function to checkTypeCompat. Tries to type cast one of the given | ||
| 7446 | expressions so that they become type compatible." | ||
| 7447 | input DAE.Exp inExp1; | ||
| 7448 | input DAE.Type inType1; | ||
| 7449 | input DAE.Exp inExp2; | ||
| 7450 | input DAE.Type inType2; | ||
| 7451 | input Boolean inAllowUnknown; | ||
| 7452 | output DAE.Exp outExp1 = inExp1; | ||
| 7453 | output DAE.Exp outExp2 = inExp2; | ||
| 7454 | output DAE.Type outCompatType; | ||
| 7455 | output Boolean outCompatible = true; | ||
| 7456 | protected | ||
| 7457 | DAE.Type ty1, ty2; | ||
| 7458 | Absyn.Path path; | ||
| 7459 | algorithm | ||
| 7460 | 821 | ty1 := derivedBasicType(inType1); | |
| 7461 | 821 | ty2 := derivedBasicType(inType2); | |
| 7462 | |||
| 7463 | outCompatType := match(ty1, ty2) | ||
| 7464 | // Real <-> Integer | ||
| 7465 | case (DAE.T_REAL(), DAE.T_INTEGER()) | ||
| 7466 | algorithm | ||
| 7467 | 438 | outExp2 := Expression.typeCastElements(inExp2, DAE.T_REAL_DEFAULT); | |
| 7468 | then | ||
| 7469 | DAE.T_REAL_DEFAULT; | ||
| 7470 | |||
| 7471 | case (DAE.T_INTEGER(), DAE.T_REAL()) | ||
| 7472 | algorithm | ||
| 7473 | 350 | outExp1 := Expression.typeCastElements(inExp1, DAE.T_REAL_DEFAULT); | |
| 7474 | then | ||
| 7475 | DAE.T_REAL_DEFAULT; | ||
| 7476 | |||
| 7477 | // If one of the expressions is boxed, unbox it. | ||
| 7478 | case (DAE.T_METABOXED(), _) | ||
| 7479 | algorithm | ||
| 7480 | 3 | (outExp1, outExp2, outCompatType, outCompatible) := | |
| 7481 | checkTypeCompat(inExp1, ty1.ty, inExp2, ty2, inAllowUnknown); | ||
| 7482 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
|
3 | outExp1 := if isBoxedType(ty2) then outExp1 else DAE.UNBOX(outExp1, outCompatType); |
| 7483 | then | ||
| 7484 | ty2; | ||
| 7485 | |||
| 7486 | case (_, DAE.T_METABOXED()) | ||
| 7487 | algorithm | ||
| 7488 | 1 | (outExp1, outExp2, outCompatType, outCompatible) := | |
| 7489 | checkTypeCompat(inExp1, ty1, inExp2, ty2.ty, inAllowUnknown); | ||
| 7490 |
1/2✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
|
1 | outExp2 := if isBoxedType(ty1) then outExp2 else DAE.UNBOX(outExp2, outCompatType); |
| 7491 | then | ||
| 7492 | ty1; | ||
| 7493 | |||
| 7494 | // Expressions such as Absyn.IDENT gets the type T_METARECORD(Absyn.Path.IDENT) | ||
| 7495 | // instead of UNIONTYPE(Absyn.Path), but e.g. a function returning an | ||
| 7496 | // Absyn.PATH has the type UNIONTYPE(Absyn.PATH). So we'll just pretend that | ||
| 7497 | // metarecords actually have uniontype type. | ||
| 7498 | case (DAE.T_METARECORD(), DAE.T_METAUNIONTYPE()) | ||
| 7499 | algorithm | ||
| 7500 | 12 | outCompatible := AbsynUtil.pathEqual(ty1.utPath, ty2.path); | |
| 7501 | then | ||
| 7502 | ty2; | ||
| 7503 | |||
| 7504 | case (DAE.T_METAUNIONTYPE(), DAE.T_METARECORD()) | ||
| 7505 | algorithm | ||
| 7506 | 9 | outCompatible := AbsynUtil.pathEqual(ty1.path, ty2.utPath); | |
| 7507 | then | ||
| 7508 | ty1; | ||
| 7509 | |||
| 7510 | // Allow unknown types in some cases, e.g. () has type T_METALIST(T_UNKNOWN) | ||
| 7511 | case (DAE.T_UNKNOWN(), _) | ||
| 7512 | algorithm | ||
| 7513 | 7 | outCompatible := inAllowUnknown; | |
| 7514 | then | ||
| 7515 | ty2; | ||
| 7516 | |||
| 7517 | case (_, DAE.T_UNKNOWN()) | ||
| 7518 | algorithm | ||
| 7519 | //print("Unknown(" + boolString(inAllowUnknown) + ")\n"); | ||
| 7520 | 1 | outCompatible := inAllowUnknown; | |
| 7521 | then | ||
| 7522 | ty1; | ||
| 7523 | |||
| 7524 | // Anything else is not compatible. | ||
| 7525 | else | ||
| 7526 | algorithm | ||
| 7527 | ✗ | outCompatible := false; | |
| 7528 | then | ||
| 7529 | DAE.T_UNKNOWN_DEFAULT; | ||
| 7530 | |||
| 7531 | end match; | ||
| 7532 | end checkTypeCompat_cast; | ||
| 7533 | |||
| 7534 | public function arrayHasUnknownDims | ||
| 7535 | "Checks if an array type has dimensions which are unknown." | ||
| 7536 | input DAE.Type inType; | ||
| 7537 | output Boolean outUnknownDims; | ||
| 7538 | algorithm | ||
| 7539 | outUnknownDims := match inType | ||
| 7540 | case DAE.T_ARRAY() | ||
| 7541 |
3/4✓ Branch 1 taken 678 times.
✓ Branch 2 taken 27 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 678 times.
|
705 | then List.any(inType.dims, Expression.dimensionUnknown) or |
| 7542 | arrayHasUnknownDims(inType.ty); | ||
| 7543 | |||
| 7544 | else false; | ||
| 7545 | end match; | ||
| 7546 | end arrayHasUnknownDims; | ||
| 7547 | |||
| 7548 | public function metaArrayElementType | ||
| 7549 | input DAE.Type inType; | ||
| 7550 | output DAE.Type outType; | ||
| 7551 | algorithm | ||
| 7552 | outType := match inType | ||
| 7553 | 134 | case DAE.T_METAARRAY() then inType.ty; | |
| 7554 | ✗ | case DAE.T_METATYPE() then metaArrayElementType(inType.ty); | |
| 7555 | end match; | ||
| 7556 | end metaArrayElementType; | ||
| 7557 | |||
| 7558 | public function isMetaArray | ||
| 7559 | input DAE.Type inType; | ||
| 7560 | output Boolean b; | ||
| 7561 | algorithm | ||
| 7562 | b := match inType | ||
| 7563 | case DAE.T_METAARRAY() then true; | ||
| 7564 | 213 | case DAE.T_METATYPE() then isMetaArray(inType.ty); | |
| 7565 | else false; | ||
| 7566 | end match; | ||
| 7567 | end isMetaArray; | ||
| 7568 | |||
| 7569 | public function getAttributes | ||
| 7570 | input DAE.Type inType; | ||
| 7571 | output list<DAE.Var> outAttributes; | ||
| 7572 | algorithm | ||
| 7573 | outAttributes := match inType | ||
| 7574 | 344 | case DAE.T_REAL() then inType.varLst; | |
| 7575 | ✗ | case DAE.T_INTEGER() then inType.varLst; | |
| 7576 | ✗ | case DAE.T_STRING() then inType.varLst; | |
| 7577 | ✗ | case DAE.T_BOOL() then inType.varLst; | |
| 7578 | ✗ | case DAE.T_ENUMERATION() then inType.attributeLst; | |
| 7579 | ✗ | case DAE.T_SUBTYPE_BASIC() then getAttributes(inType.complexType); | |
| 7580 | else {}; | ||
| 7581 | end match; | ||
| 7582 | end getAttributes; | ||
| 7583 | |||
| 7584 | public function lookupAttributeValue | ||
| 7585 | input list<DAE.Var> inAttributes; | ||
| 7586 | input String inName; | ||
| 7587 | output Option<Values.Value> outValue = NONE(); | ||
| 7588 | algorithm | ||
| 7589 |
1/2✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
|
78 | for attr in inAttributes loop |
| 7590 |
4/4✓ Branch 1 taken 48 times.
✓ Branch 2 taken 30 times.
✓ Branch 5 taken 32 times.
✓ Branch 6 taken 16 times.
|
78 | if inName == TypesDump.getVarName(attr) then |
| 7591 | 32 | outValue := DAEUtil.bindingValue(varBinding(attr)); | |
| 7592 | 32 | break; | |
| 7593 | end if; | ||
| 7594 | end for; | ||
| 7595 | end lookupAttributeValue; | ||
| 7596 | |||
| 7597 | public function lookupAttributeExp | ||
| 7598 | input list<DAE.Var> inAttributes; | ||
| 7599 | input String inName; | ||
| 7600 | output Option<DAE.Exp> outExp = NONE(); | ||
| 7601 | algorithm | ||
| 7602 |
2/2✓ Branch 0 taken 808 times.
✓ Branch 1 taken 146 times.
|
954 | for attr in inAttributes loop |
| 7603 |
4/4✓ Branch 1 taken 291 times.
✓ Branch 2 taken 517 times.
✓ Branch 5 taken 180 times.
✓ Branch 6 taken 111 times.
|
808 | if inName == TypesDump.getVarName(attr) then |
| 7604 | 180 | outExp := DAEUtil.bindingExp(varBinding(attr)); | |
| 7605 | 180 | break; | |
| 7606 | end if; | ||
| 7607 | end for; | ||
| 7608 | end lookupAttributeExp; | ||
| 7609 | |||
| 7610 | protected function unboxedTypeTraverseHelper<T> | ||
| 7611 | input DAE.Type ty; | ||
| 7612 | input T dummy; | ||
| 7613 | output DAE.Type oty = unboxedType(ty); | ||
| 7614 | output T odummy = dummy; | ||
| 7615 | end unboxedTypeTraverseHelper; | ||
| 7616 | |||
| 7617 | public function getMetaRecordFields | ||
| 7618 | input DAE.Type ty; | ||
| 7619 | output list<DAE.Var> fields; | ||
| 7620 | algorithm | ||
| 7621 | fields := match ty | ||
| 7622 | local | ||
| 7623 | DAE.EvaluateSingletonTypeFunction fun; | ||
| 7624 | case DAE.T_METARECORD(fields=fields) then fields; | ||
| 7625 | case DAE.T_METAUNIONTYPE(knownSingleton=false) | ||
| 7626 | algorithm | ||
| 7627 | ✗ | Error.addInternalError(getInstanceName() + " called on a non-singleton uniontype: " + TypesDump.unparseType(ty), sourceInfo()); | |
| 7628 | ✗ | then fail(); | |
| 7629 | case DAE.T_METAUNIONTYPE(singletonType=DAE.EVAL_SINGLETON_KNOWN_TYPE(ty=DAE.T_METARECORD(fields=fields))) then fields; | ||
| 7630 | case DAE.T_METAUNIONTYPE(singletonType=DAE.EVAL_SINGLETON_TYPE_FUNCTION(fun=fun)) | ||
| 7631 | algorithm | ||
| 7632 |
2/4✓ Branch 0 taken 416 times.
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 416 times.
|
416 | DAE.T_METARECORD(fields=fields) := fun(); |
| 7633 | then fields; | ||
| 7634 | else | ||
| 7635 | algorithm | ||
| 7636 | ✗ | Error.addInternalError(getInstanceName() + " called on a non-singleton uniontype: " + TypesDump.unparseType(ty), sourceInfo()); | |
| 7637 | ✗ | then fail(); | |
| 7638 | end match; | ||
| 7639 | end getMetaRecordFields; | ||
| 7640 | |||
| 7641 | public function getMetaRecordIfSingleton | ||
| 7642 | input DAE.Type ty; | ||
| 7643 | output DAE.Type oty; | ||
| 7644 | algorithm | ||
| 7645 | oty := match ty | ||
| 7646 | local | ||
| 7647 | DAE.EvaluateSingletonTypeFunction fun; | ||
| 7648 | case DAE.T_METAUNIONTYPE(knownSingleton=false) then ty; | ||
| 7649 | ✗ | case DAE.T_METAUNIONTYPE(singletonType=DAE.EVAL_SINGLETON_KNOWN_TYPE(ty=oty)) then setTypeVariables(oty, ty.typeVars); | |
| 7650 | case DAE.T_METAUNIONTYPE(singletonType=DAE.EVAL_SINGLETON_TYPE_FUNCTION(fun=fun)) | ||
| 7651 | algorithm | ||
| 7652 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | oty := fun(); |
| 7653 | 50 | then setTypeVariables(oty, ty.typeVars); | |
| 7654 | else ty; | ||
| 7655 | end match; | ||
| 7656 | end getMetaRecordIfSingleton; | ||
| 7657 | |||
| 7658 | public function setTypeVariables | ||
| 7659 | input DAE.Type ty; | ||
| 7660 | input list<DAE.Type> typeVars; | ||
| 7661 | output DAE.Type oty; | ||
| 7662 | algorithm | ||
| 7663 | oty := match ty | ||
| 7664 | case oty as DAE.T_METAUNIONTYPE() | ||
| 7665 | algorithm | ||
| 7666 | 98 | oty.typeVars := typeVars; | |
| 7667 | then oty; | ||
| 7668 | case oty as DAE.T_METARECORD() | ||
| 7669 | algorithm | ||
| 7670 | 50 | oty.typeVars := typeVars; | |
| 7671 | then oty; | ||
| 7672 | else ty; | ||
| 7673 | end match; | ||
| 7674 | end setTypeVariables; | ||
| 7675 | |||
| 7676 | public function isExpandableConnector | ||
| 7677 | "@author: adrpo | ||
| 7678 | this function checks if the given type is an expandable connector" | ||
| 7679 | input DAE.Type ty; | ||
| 7680 | output Boolean isExpandable; | ||
| 7681 | algorithm | ||
| 7682 | isExpandable := match ty | ||
| 7683 | case DAE.T_COMPLEX(complexClassType = ClassInf.CONNECTOR(_,true)) then true; | ||
| 7684 | // TODO! check if subtype is needed here | ||
| 7685 | case DAE.T_SUBTYPE_BASIC(complexClassType = ClassInf.CONNECTOR(_,true)) then true; | ||
| 7686 | else false; | ||
| 7687 | end match; | ||
| 7688 | end isExpandableConnector; | ||
| 7689 | |||
| 7690 | public function getBasicType | ||
| 7691 | input DAE.Type ty; | ||
| 7692 | output DAE.Type outType; | ||
| 7693 | algorithm | ||
| 7694 | outType := match ty | ||
| 7695 | 13 | case DAE.Type.T_ARRAY() then getBasicType(ty.ty); | |
| 7696 | ✗ | case DAE.Type.T_SUBTYPE_BASIC() then getBasicType(ty.complexType); | |
| 7697 | else ty; | ||
| 7698 | end match; | ||
| 7699 | end getBasicType; | ||
| 7700 | |||
| 7701 | public function resultExps | ||
| 7702 | "Collects the result expressions of a list of match-expression cases. | ||
| 7703 | Moved here from Patternm so Types does not depend on the instantiation cluster." | ||
| 7704 | input list<DAE.MatchCase> inCases; | ||
| 7705 | output list<DAE.Exp> exps; | ||
| 7706 | algorithm | ||
| 7707 | exps := match inCases | ||
| 7708 | local | ||
| 7709 | DAE.Exp exp; list<DAE.MatchCase> cases; | ||
| 7710 | case {} then {}; | ||
| 7711 | case DAE.CASE(result=SOME(exp))::cases | ||
| 7712 | algorithm | ||
| 7713 | 16 | exps := resultExps(cases); | |
| 7714 | then exp::exps; | ||
| 7715 | ✗ | case _::cases then resultExps(cases); | |
| 7716 | end match; | ||
| 7717 | end resultExps; | ||
| 7718 | |||
| 7719 | public function fixCaseReturnTypes2 | ||
| 7720 | "Replaces the result expressions of a list of match-expression cases. | ||
| 7721 | Moved here from Patternm (see resultExps)." | ||
| 7722 | input list<DAE.MatchCase> inCases; | ||
| 7723 | input list<DAE.Exp> inExps; | ||
| 7724 | input SourceInfo inInfo; | ||
| 7725 | output list<DAE.MatchCase> outCases; | ||
| 7726 | algorithm | ||
| 7727 | outCases := matchcontinue (inCases,inExps,inInfo) | ||
| 7728 | local | ||
| 7729 | list<DAE.Pattern> patterns; | ||
| 7730 | list<DAE.Element> decls; | ||
| 7731 | list<DAE.Statement> body; | ||
| 7732 | Option<DAE.Exp> patternGuard; | ||
| 7733 | DAE.Exp exp; | ||
| 7734 | DAE.MatchCase case_; | ||
| 7735 | Integer jump; | ||
| 7736 | SourceInfo resultInfo,info2; | ||
| 7737 | list<DAE.MatchCase> cases; | ||
| 7738 | list<DAE.Exp> exps; | ||
| 7739 | SourceInfo info; | ||
| 7740 | |||
| 7741 | case ({},{},_) then {}; | ||
| 7742 | |||
| 7743 | case (DAE.CASE(patterns,patternGuard,decls,body,SOME(_),resultInfo,jump,info2)::cases,exp::exps,info) | ||
| 7744 | algorithm | ||
| 7745 | 5082 | cases := fixCaseReturnTypes2(cases,exps,info); | |
| 7746 | 5082 | then DAE.CASE(patterns,patternGuard,decls,body,SOME(exp),resultInfo,jump,info2)::cases; | |
| 7747 | |||
| 7748 | case ((case_ as DAE.CASE(result=NONE()))::cases,exps,info) | ||
| 7749 | algorithm | ||
| 7750 | 90 | cases := fixCaseReturnTypes2(cases,exps,info); | |
| 7751 | then case_::cases; | ||
| 7752 | |||
| 7753 | else | ||
| 7754 | algorithm | ||
| 7755 | ✗ | Error.addSourceMessage(Error.INTERNAL_ERROR, {"Types.fixCaseReturnTypes2 failed"}, inInfo); | |
| 7756 | ✗ | then fail(); | |
| 7757 | end matchcontinue; | ||
| 7758 | end fixCaseReturnTypes2; | ||
| 7759 | |||
| 7760 | annotation(__OpenModelica_Interface="frontend_base"); | ||
| 7761 | end Types; | ||
| 7762 |