OMCompiler/Compiler/FrontEnd/AbsynToSCode.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 AbsynToSCode | ||
| 37 | " file: AbsynToSCode.mo | ||
| 38 | package: AbsynToSCode | ||
| 39 | description: AbsynToSCode translates Absyn to SCode intermediate form | ||
| 40 | |||
| 41 | |||
| 42 | This module contains functions to translate from | ||
| 43 | an Absyn data representation to a simplified version | ||
| 44 | called SCode. | ||
| 45 | The most important function in this module is the *translateAbsyn2SCode* | ||
| 46 | function which turns an abstract syntax tree into an SCode | ||
| 47 | representation. Also *translateClass*, *translateMod*, etc. | ||
| 48 | |||
| 49 | The SCode representation is then used as input to the Inst module" | ||
| 50 | |||
| 51 | public import Absyn; | ||
| 52 | public import AbsynUtil; | ||
| 53 | public import SCode; | ||
| 54 | |||
| 55 | protected | ||
| 56 | import BackendInterface; | ||
| 57 | import Config; | ||
| 58 | import Debug; | ||
| 59 | import Error; | ||
| 60 | import Flags; | ||
| 61 | import List; | ||
| 62 | import MetaUtil; | ||
| 63 | import SCodeUtil; | ||
| 64 | import System; | ||
| 65 | import Util; | ||
| 66 | import MetaModelica.Dangerous; | ||
| 67 | import Dump; | ||
| 68 | |||
| 69 | // Constant expression for AssertionLevel.error. | ||
| 70 | protected constant Absyn.Exp ASSERTION_LEVEL_ERROR = Absyn.CREF(Absyn.CREF_FULLYQUALIFIED( | ||
| 71 | Absyn.CREF_QUAL("AssertionLevel", {}, Absyn.CREF_IDENT("error", {})))); | ||
| 72 | |||
| 73 | public function translateAbsyn2SCode | ||
| 74 | "This function takes an Absyn.Program | ||
| 75 | and constructs a SCode.Program from it. | ||
| 76 | This particular version of translate tries to fix any uniontypes | ||
| 77 | in the inProgram before translating further. This should probably | ||
| 78 | be moved into Parser.parse since you have to modify the tree every | ||
| 79 | single time you translate..." | ||
| 80 | input Absyn.Program inProgram; | ||
| 81 | output SCode.Program outProgram; | ||
| 82 | algorithm | ||
| 83 | outProgram := match inProgram | ||
| 84 | local | ||
| 85 | SCode.Program sp; | ||
| 86 | list<Absyn.Class> inClasses; | ||
| 87 | |||
| 88 | case _ | ||
| 89 | algorithm | ||
| 90 | 6486 | BackendInterface.initInstHashTable(); | |
| 91 | // adrpo: TODO! FIXME! disable function caching for now as some tests fail. | ||
| 92 | // setGlobalRoot(Ceval.cevalHashIndex, Ceval.emptyCevalHashTable()); | ||
| 93 | 6486 | Absyn.PROGRAM(classes=inClasses) := MetaUtil.createMetaClassesInProgram(inProgram); | |
| 94 | |||
| 95 | // set the external flag that signals the presence of inner/outer components in the model | ||
| 96 | 6486 | System.setHasInnerOuterDefinitions(false); | |
| 97 | // set the external flag that signals the presence of expandable connectors in the model | ||
| 98 | 6486 | System.setHasExpandableConnectors(false); | |
| 99 | // set the external flag that signals the presence of overconstrained connectors in the model | ||
| 100 | 6486 | System.setHasOverconstrainedConnectors(false); | |
| 101 | // set the external flag that signals the presence of expandable connectors in the model | ||
| 102 | 6486 | System.setHasStreamConnectors(false); | |
| 103 | |||
| 104 | // translate given absyn to scode. | ||
| 105 |
4/4✓ Branch 0 taken 176542 times.
✓ Branch 1 taken 6486 times.
✓ Branch 2 taken 176542 times.
✓ Branch 3 taken 6486 times.
|
183028 | sp := list(translateClass(c) for c in inClasses); |
| 106 | |||
| 107 | // adrpo: note that WE DO NOT NEED to add initial functions to the program | ||
| 108 | // as they are already part of the initialEnv done by Builtin.initialGraph | ||
| 109 | then | ||
| 110 | sp; | ||
| 111 | end match; | ||
| 112 | end translateAbsyn2SCode; | ||
| 113 | |||
| 114 | public function translateClass | ||
| 115 | input Absyn.Class inClass; | ||
| 116 | output SCode.Element outClass; | ||
| 117 | algorithm | ||
| 118 | 742809 | outClass := translateClass2(inClass, Error.getNumMessages()); | |
| 119 | end translateClass; | ||
| 120 | |||
| 121 | protected function translateClass2 | ||
| 122 | "This functions converts an Absyn.Class to a SCode.Class." | ||
| 123 | input Absyn.Class inClass; | ||
| 124 | input Integer inNumMessages; | ||
| 125 | output SCode.Element outClass; | ||
| 126 | algorithm | ||
| 127 | outClass := matchcontinue inClass | ||
| 128 | local | ||
| 129 | SCode.ClassDef d_1; | ||
| 130 | SCode.Restriction r_1; | ||
| 131 | Absyn.Class c; | ||
| 132 | String n; | ||
| 133 | Boolean p,f,e; | ||
| 134 | Absyn.Restriction r; | ||
| 135 | Absyn.ClassDef d; | ||
| 136 | SourceInfo file_info; | ||
| 137 | SCode.Element scodeClass; | ||
| 138 | SCode.Final sFin; | ||
| 139 | SCode.Encapsulated sEnc; | ||
| 140 | SCode.Partial sPar; | ||
| 141 | SCode.Comment cmt; | ||
| 142 | |||
| 143 | case c as Absyn.CLASS(name = n,partialPrefix = p,finalPrefix = f,encapsulatedPrefix = e,restriction = r,body = d,info = file_info) | ||
| 144 | algorithm | ||
| 145 | // fprint(Flags.TRANSLATE, "Translating class:" + n + "\n"); | ||
| 146 | 742809 | r_1 := translateRestriction(c, r); // uniontype will not get translated! | |
| 147 | 742809 | (d_1,cmt) := translateClassdef(d,file_info,r_1); | |
| 148 | 742809 | sFin := SCodeUtil.boolFinal(f); | |
| 149 | 742809 | sEnc := SCodeUtil.boolEncapsulated(e); | |
| 150 | 742809 | sPar := SCodeUtil.boolPartial(p); | |
| 151 | 742809 | scodeClass := | |
| 152 | SCode.CLASS( | ||
| 153 | n, | ||
| 154 | SCode.PREFIXES( // here we set only final as is a top level class! | ||
| 155 | SCode.PUBLIC(), | ||
| 156 | SCode.NOT_REDECLARE(), | ||
| 157 | sFin, | ||
| 158 | Absyn.NOT_INNER_OUTER(), | ||
| 159 | SCode.NOT_REPLACEABLE()), | ||
| 160 | sEnc, | ||
| 161 | sPar, | ||
| 162 | r_1, | ||
| 163 | d_1, | ||
| 164 | cmt, | ||
| 165 | file_info); | ||
| 166 | then | ||
| 167 | scodeClass; | ||
| 168 | |||
| 169 | case Absyn.CLASS(name = n,info = file_info) | ||
| 170 | algorithm | ||
| 171 | // Print out an internal error msg only if no other errors have already | ||
| 172 | // been printed. | ||
| 173 | ✗ | true := intEq(Error.getNumMessages(), inNumMessages); | |
| 174 | ✗ | n := "AbsynToSCode.translateClass2 failed: " + n; | |
| 175 | ✗ | Error.addSourceMessage(Error.INTERNAL_ERROR,{n},file_info); | |
| 176 | ✗ | then | |
| 177 | fail(); | ||
| 178 | end matchcontinue; | ||
| 179 | end translateClass2; | ||
| 180 | |||
| 181 | |||
| 182 | //mahge: FIX HERE. Check for proper input and output | ||
| 183 | //declarations in operators according to the specifications. | ||
| 184 | public function translateOperatorDef | ||
| 185 | input Absyn.ClassDef inClassDef; | ||
| 186 | input Absyn.Ident operatorName; | ||
| 187 | input SourceInfo info; | ||
| 188 | output SCode.ClassDef outOperDef; | ||
| 189 | output SCode.Comment cmt; | ||
| 190 | algorithm | ||
| 191 | (outOperDef,cmt) := match inClassDef | ||
| 192 | local | ||
| 193 | Option<String> cmtString; | ||
| 194 | list<SCode.Element> els; | ||
| 195 | list<Absyn.ClassPart> parts; | ||
| 196 | list<Absyn.Annotation> aann; | ||
| 197 | Option<SCode.Annotation> ann; | ||
| 198 | |||
| 199 | case Absyn.PARTS(classParts = parts,ann=aann, comment = cmtString) | ||
| 200 | algorithm | ||
| 201 | 1922 | els := translateClassdefElements(parts); | |
| 202 | 1922 | cmt := translateCommentList(aann,cmtString); | |
| 203 | 1922 | then | |
| 204 | (SCode.PARTS(els,{},{},{},{},{},{},NONE()),cmt); | ||
| 205 | else | ||
| 206 | algorithm | ||
| 207 | ✗ | Error.addSourceMessage(Error.INTERNAL_ERROR, {"Could not translate operator to SCode because it is not using class parts."}, info); | |
| 208 | ✗ | then fail(); | |
| 209 | end match; | ||
| 210 | end translateOperatorDef; | ||
| 211 | |||
| 212 | public function getOperatorGivenName | ||
| 213 | input SCode.Element inOperatorFunction; | ||
| 214 | output Absyn.Path outName; | ||
| 215 | algorithm | ||
| 216 | outName := match inOperatorFunction | ||
| 217 | local | ||
| 218 | SCode.Ident name; | ||
| 219 | case SCode.CLASS(name,_,_,_,SCode.R_FUNCTION(SCode.FR_OPERATOR_FUNCTION()),_,_,_) | ||
| 220 | ✗ | then Absyn.IDENT(name); | |
| 221 | |||
| 222 | end match; | ||
| 223 | end getOperatorGivenName; | ||
| 224 | |||
| 225 | public function getOperatorQualName | ||
| 226 | input SCode.Element inOperatorFunction; | ||
| 227 | input SCode.Ident operName; | ||
| 228 | output SCode.Path outName; | ||
| 229 | algorithm | ||
| 230 | outName := match (inOperatorFunction,operName) | ||
| 231 | local | ||
| 232 | SCode.Ident name,opname; | ||
| 233 | case (SCode.CLASS(name,_,_,_,SCode.R_FUNCTION(_),_,_,_),opname) | ||
| 234 | 97 | then AbsynUtil.joinPaths(Absyn.IDENT(opname), Absyn.IDENT(name)); | |
| 235 | |||
| 236 | end match; | ||
| 237 | end getOperatorQualName; | ||
| 238 | |||
| 239 | |||
| 240 | public function getListofQualOperatorFuncsfromOperator | ||
| 241 | input SCode.Element inOperator; | ||
| 242 | output list<SCode.Path> outNames; | ||
| 243 | algorithm | ||
| 244 | outNames := match inOperator | ||
| 245 | local | ||
| 246 | list<SCode.Element> els; | ||
| 247 | SCode.Ident opername; | ||
| 248 | list<SCode.Path> names; | ||
| 249 | |||
| 250 | //If operator get the list of functions in it. | ||
| 251 | case SCode.CLASS(opername,_,_,_, SCode.R_OPERATOR() ,SCode.PARTS(elementLst = els),_,_) | ||
| 252 | algorithm | ||
| 253 | 88 | names := List.map1(els,getOperatorQualName,opername); | |
| 254 | then | ||
| 255 | names; | ||
| 256 | |||
| 257 | //If operator function return its name | ||
| 258 | case SCode.CLASS(opername,_,_,_, SCode.R_FUNCTION(SCode.FR_OPERATOR_FUNCTION()),_,_,_) | ||
| 259 | algorithm | ||
| 260 | 11 | names := {Absyn.IDENT(opername)}; | |
| 261 | then | ||
| 262 | names; | ||
| 263 | end match; | ||
| 264 | end getListofQualOperatorFuncsfromOperator; | ||
| 265 | |||
| 266 | public function translateRestriction | ||
| 267 | "Convert a class restriction." | ||
| 268 | input Absyn.Class inClass; | ||
| 269 | input Absyn.Restriction inRestriction; | ||
| 270 | output SCode.Restriction outRestriction; | ||
| 271 | algorithm | ||
| 272 | outRestriction := match (inClass,inRestriction) | ||
| 273 | local | ||
| 274 | Absyn.Class d; | ||
| 275 | Absyn.Path name; | ||
| 276 | Integer index; | ||
| 277 | Boolean singleton, moved; | ||
| 278 | Absyn.FunctionPurity purity; | ||
| 279 | list<String> typeVars; | ||
| 280 | |||
| 281 | // ?? Only normal functions can have 'external' | ||
| 282 | case (d,Absyn.R_FUNCTION(Absyn.FR_NORMAL_FUNCTION(purity))) | ||
| 283 |
2/2✓ Branch 1 taken 3332007 times.
✓ Branch 2 taken 1250740 times.
|
4582747 | then if containsExternalFuncDecl(d) |
| 284 | then SCode.R_FUNCTION(SCode.FR_EXTERNAL_FUNCTION(purity)) | ||
| 285 | else SCode.R_FUNCTION(SCode.FR_NORMAL_FUNCTION(purity)); | ||
| 286 | |||
| 287 | case (_,Absyn.R_FUNCTION(Absyn.FR_OPERATOR_FUNCTION())) then SCode.R_FUNCTION(SCode.FR_OPERATOR_FUNCTION()); | ||
| 288 | case (_,Absyn.R_FUNCTION(Absyn.FR_PARALLEL_FUNCTION())) then SCode.R_FUNCTION(SCode.FR_PARALLEL_FUNCTION()); | ||
| 289 | case (_,Absyn.R_FUNCTION(Absyn.FR_KERNEL_FUNCTION())) then SCode.R_FUNCTION(SCode.FR_KERNEL_FUNCTION()); | ||
| 290 | |||
| 291 | case (_,Absyn.R_CLASS()) then SCode.R_CLASS(); | ||
| 292 | case (_,Absyn.R_OPTIMIZATION()) then SCode.R_OPTIMIZATION(); | ||
| 293 | case (_,Absyn.R_MODEL()) then SCode.R_MODEL(); | ||
| 294 | case (_,Absyn.R_RECORD()) then SCode.R_RECORD(false); | ||
| 295 | case (_,Absyn.R_OPERATOR_RECORD()) then SCode.R_RECORD(true); | ||
| 296 | |||
| 297 | case (_,Absyn.R_BLOCK()) then SCode.R_BLOCK(); | ||
| 298 | |||
| 299 | case (_,Absyn.R_CONNECTOR()) then SCode.R_CONNECTOR(false); | ||
| 300 | 4436 | case (_,Absyn.R_EXP_CONNECTOR()) algorithm System.setHasExpandableConnectors(true); then SCode.R_CONNECTOR(true); | |
| 301 | |||
| 302 | case (_,Absyn.R_OPERATOR()) then SCode.R_OPERATOR(); | ||
| 303 | |||
| 304 | case (_,Absyn.R_TYPE()) then SCode.R_TYPE(); | ||
| 305 | case (_,Absyn.R_PACKAGE()) then SCode.R_PACKAGE(); | ||
| 306 | case (_,Absyn.R_ENUMERATION()) then SCode.R_ENUMERATION(); | ||
| 307 | case (_,Absyn.R_PREDEFINED_INTEGER()) then SCode.R_PREDEFINED_INTEGER(); | ||
| 308 | case (_,Absyn.R_PREDEFINED_REAL()) then SCode.R_PREDEFINED_REAL(); | ||
| 309 | case (_,Absyn.R_PREDEFINED_STRING()) then SCode.R_PREDEFINED_STRING(); | ||
| 310 | case (_,Absyn.R_PREDEFINED_BOOLEAN()) then SCode.R_PREDEFINED_BOOLEAN(); | ||
| 311 | // BTH | ||
| 312 | case (_,Absyn.R_PREDEFINED_CLOCK()) then SCode.R_PREDEFINED_CLOCK(); | ||
| 313 | case (_,Absyn.R_PREDEFINED_ENUMERATION()) then SCode.R_PREDEFINED_ENUMERATION(); | ||
| 314 | |||
| 315 | case (_,Absyn.R_METARECORD(name,index,singleton,moved,typeVars)) //MetaModelica extension, added by x07simbj | ||
| 316 |
4/4✓ Branch 0 taken 8203 times.
✓ Branch 1 taken 8203 times.
✓ Branch 2 taken 14054 times.
✓ Branch 3 taken 2352 times.
|
38663 | then SCode.R_METARECORD(name,index,singleton,moved,typeVars); |
| 317 | 2621 | case (Absyn.CLASS(body=Absyn.PARTS(typeVars=typeVars)),Absyn.R_UNIONTYPE()) then SCode.R_UNIONTYPE(typeVars); /*MetaModelica extension added by x07simbj */ | |
| 318 | case (_,Absyn.R_UNIONTYPE()) then SCode.R_UNIONTYPE({}); /*MetaModelica extension added by x07simbj */ | ||
| 319 | |||
| 320 | end match; | ||
| 321 | end translateRestriction; | ||
| 322 | |||
| 323 | protected function containsExternalFuncDecl | ||
| 324 | "Returns true if the Absyn.Class contains an external function declaration." | ||
| 325 | input Absyn.Class inClass; | ||
| 326 | output Boolean outBoolean; | ||
| 327 | algorithm | ||
| 328 | outBoolean := match inClass | ||
| 329 | local | ||
| 330 | list<Absyn.ClassPart> parts; | ||
| 331 | 4307800 | case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) then List.any(parts,AbsynUtil.isExternalPart); | |
| 332 | 162266 | case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) then List.any(parts,AbsynUtil.isExternalPart); | |
| 333 | else false; | ||
| 334 | end match; | ||
| 335 | end containsExternalFuncDecl; | ||
| 336 | |||
| 337 | protected function translateAttributes | ||
| 338 | "@author: adrpo | ||
| 339 | translates from Absyn.ElementAttributes to SCode.Attributes" | ||
| 340 | input Absyn.ElementAttributes inEA; | ||
| 341 | input list<Absyn.Subscript> extraArrayDim; | ||
| 342 | output SCode.Attributes outA; | ||
| 343 | algorithm | ||
| 344 | outA := match(inEA,extraArrayDim) | ||
| 345 | local | ||
| 346 | Boolean f, s; | ||
| 347 | Absyn.Variability v; | ||
| 348 | Absyn.Parallelism p; | ||
| 349 | Absyn.ArrayDim adim,extraADim; | ||
| 350 | Absyn.Direction dir; | ||
| 351 | Absyn.IsField fi; | ||
| 352 | SCode.ConnectorType ct; | ||
| 353 | SCode.Parallelism sp; | ||
| 354 | SCode.Variability sv; | ||
| 355 | |||
| 356 | case (Absyn.ATTR(f, s, p, v, dir, fi, adim),extraADim) | ||
| 357 | algorithm | ||
| 358 | 648811 | ct := translateConnectorType(f, s); | |
| 359 | 648811 | sv := translateVariability(v); | |
| 360 | 648811 | sp := translateParallelism(p); | |
| 361 | 648811 | adim := listAppend(extraADim, adim); | |
| 362 | 648811 | then | |
| 363 | SCode.ATTR(adim, ct, sp, sv, dir, fi); | ||
| 364 | end match; | ||
| 365 | end translateAttributes; | ||
| 366 | |||
| 367 | protected function translateConnectorType | ||
| 368 | input Boolean inFlow; | ||
| 369 | input Boolean inStream; | ||
| 370 | output SCode.ConnectorType outType; | ||
| 371 | algorithm | ||
| 372 | outType := match(inFlow, inStream) | ||
| 373 | case (false, false) then SCode.POTENTIAL(); | ||
| 374 | case (true, false) then SCode.FLOW(); | ||
| 375 | case (false, true) then SCode.STREAM(); | ||
| 376 | // Both flow and stream is not allowed by the grammar, so this shouldn't be | ||
| 377 | // possible. | ||
| 378 | case (true, true) | ||
| 379 | algorithm | ||
| 380 | ✗ | Error.addMessage(Error.INTERNAL_ERROR, | |
| 381 | {"AbsynToSCode.translateConnectorType got both flow and stream prefix."}); | ||
| 382 | ✗ | then | |
| 383 | fail(); | ||
| 384 | end match; | ||
| 385 | end translateConnectorType; | ||
| 386 | |||
| 387 | protected function translateClassdef | ||
| 388 | "This function converts an Absyn.ClassDef to a SCode.ClassDef. | ||
| 389 | For the DERIVED case, the conversion is fairly trivial, but for | ||
| 390 | the PARTS case more work is needed. | ||
| 391 | The result contains separate lists for: | ||
| 392 | elements, equations and algorithms, which are mixed in the input. | ||
| 393 | LS: Divided the translateClassdef into separate functions for collecting the different parts" | ||
| 394 | input Absyn.ClassDef inClassDef; | ||
| 395 | input SourceInfo info; | ||
| 396 | input SCode.Restriction re; | ||
| 397 | output SCode.ClassDef outClassDef; | ||
| 398 | output SCode.Comment outComment; | ||
| 399 | algorithm | ||
| 400 | (outClassDef,outComment) := match inClassDef | ||
| 401 | local | ||
| 402 | SCode.Mod mod; | ||
| 403 | Absyn.TypeSpec t; | ||
| 404 | Absyn.ElementAttributes attr; | ||
| 405 | list<Absyn.ElementArg> a,cmod; | ||
| 406 | Option<Absyn.Comment> cmt; | ||
| 407 | Option<String> cmtString; | ||
| 408 | list<SCode.Element> els,tvels; | ||
| 409 | list<SCode.Equation> eqs,initeqs; | ||
| 410 | list<SCode.AlgorithmSection> als,initals; | ||
| 411 | list<SCode.ConstraintSection> cos; | ||
| 412 | Option<SCode.ExternalDecl> decl; | ||
| 413 | list<Absyn.ClassPart> parts; | ||
| 414 | list<String> vars; | ||
| 415 | list<SCode.Enum> lst_1; | ||
| 416 | list<Absyn.EnumLiteral> lst; | ||
| 417 | SCode.Comment scodeCmt; | ||
| 418 | Absyn.Path path; | ||
| 419 | list<Absyn.Path> pathLst; | ||
| 420 | list<String> typeVars; | ||
| 421 | SCode.Attributes scodeAttr; | ||
| 422 | list<Absyn.NamedArg> classAttrs; | ||
| 423 | list<Absyn.Annotation> ann; | ||
| 424 | |||
| 425 | case Absyn.DERIVED(typeSpec = t,attributes = attr,arguments = a,comment = cmt) | ||
| 426 | algorithm | ||
| 427 | 648811 | checkTypeSpec(t, info); | |
| 428 | // fprintln(Flags.TRANSLATE, "translating derived class: " + Dump.unparseTypeSpec(t)); | ||
| 429 | 1297622 | mod := translateMod(SOME(Absyn.CLASSMOD(a,Absyn.NOMOD())), SCode.NOT_FINAL(), SCode.NOT_EACH(), NONE(), info) "TODO: attributes of derived classes"; | |
| 430 | 648811 | scodeAttr := translateAttributes(attr, {}); | |
| 431 | 648811 | scodeCmt := translateComment(cmt); | |
| 432 | 648811 | then | |
| 433 | (SCode.DERIVED(t,mod,scodeAttr), scodeCmt); | ||
| 434 | |||
| 435 | case Absyn.PARTS(typeVars = typeVars, classAttrs = classAttrs, classParts = parts,ann=ann,comment = cmtString) | ||
| 436 | algorithm | ||
| 437 | // fprintln(Flags.TRANSLATE, "translating class parts"); | ||
| 438 | typeVars := match re | ||
| 439 | 16406 | case SCode.R_METARECORD() then List.union(typeVars, re.typeVars); | |
| 440 | 2621 | case SCode.R_UNIONTYPE() then List.union(typeVars, re.typeVars); | |
| 441 | else typeVars; | ||
| 442 | end match; | ||
| 443 | 6713827 | tvels := List.map1(typeVars, makeTypeVarElement, info); | |
| 444 | 6713827 | els := translateClassdefElements(parts); | |
| 445 | 6713827 | els := listAppend(tvels,els); | |
| 446 | 6713827 | eqs := translateClassdefEquations(parts); | |
| 447 | 6713827 | initeqs := translateClassdefInitialequations(parts); | |
| 448 | 6713827 | als := translateClassdefAlgorithms(parts); | |
| 449 | 6713827 | initals := translateClassdefInitialalgorithms(parts); | |
| 450 | 6713827 | cos := translateClassdefConstraints(parts); | |
| 451 | 6713827 | scodeCmt := translateCommentList(ann, cmtString); | |
| 452 | 6713827 | decl := translateClassdefExternaldecls(parts); | |
| 453 | 6713827 | decl := translateAlternativeExternalAnnotation(decl, scodeCmt, info); | |
| 454 | 6713827 | then | |
| 455 | (SCode.PARTS(els,eqs,initeqs,als,initals,cos,classAttrs,decl),scodeCmt); | ||
| 456 | |||
| 457 | case Absyn.ENUMERATION(Absyn.ENUMLITERALS(enumLiterals = lst), cmt) | ||
| 458 | algorithm | ||
| 459 | // fprintln(Flags.TRANSLATE, "translating enumerations"); | ||
| 460 | 170981 | lst_1 := translateEnumlist(lst); | |
| 461 | 170981 | scodeCmt := translateComment(cmt); | |
| 462 | 170981 | then | |
| 463 | (SCode.ENUMERATION(lst_1), scodeCmt); | ||
| 464 | |||
| 465 | case Absyn.ENUMERATION(Absyn.ENUM_COLON(), cmt) | ||
| 466 | algorithm | ||
| 467 | // fprintln(Flags.TRANSLATE, "translating enumeration of ':'"); | ||
| 468 | 6 | scodeCmt := translateComment(cmt); | |
| 469 | then | ||
| 470 | (SCode.ENUMERATION({}),scodeCmt); | ||
| 471 | |||
| 472 | case Absyn.OVERLOAD(pathLst,cmt) | ||
| 473 | algorithm | ||
| 474 | // fprintln(Flags.TRANSLATE, "translating overloaded"); | ||
| 475 | 59562 | scodeCmt := translateComment(cmt); | |
| 476 | 59562 | then | |
| 477 | (SCode.OVERLOAD(pathLst),scodeCmt); | ||
| 478 | |||
| 479 | case Absyn.CLASS_EXTENDS(modifications = cmod,ann=ann,comment = cmtString,parts = parts) | ||
| 480 | algorithm | ||
| 481 | // fprintln(Flags.TRANSLATE "translating model extends " + name + " ... end " + name + ";"); | ||
| 482 | 175868 | els := translateClassdefElements(parts); | |
| 483 | 175868 | eqs := translateClassdefEquations(parts); | |
| 484 | 175868 | initeqs := translateClassdefInitialequations(parts); | |
| 485 | 175868 | als := translateClassdefAlgorithms(parts); | |
| 486 | 175868 | initals := translateClassdefInitialalgorithms(parts); | |
| 487 | 175868 | cos := translateClassdefConstraints(parts); | |
| 488 | 351736 | mod := translateMod(SOME(Absyn.CLASSMOD(cmod,Absyn.NOMOD())), SCode.NOT_FINAL(), SCode.NOT_EACH(), NONE(), Absyn.dummyInfo); | |
| 489 | 175868 | scodeCmt := translateCommentList(ann, cmtString); | |
| 490 | 175868 | decl := translateClassdefExternaldecls(parts); | |
| 491 | 175868 | decl := translateAlternativeExternalAnnotation(decl, scodeCmt, info); | |
| 492 | 175868 | then | |
| 493 | (SCode.CLASS_EXTENDS(mod,SCode.PARTS(els,eqs,initeqs,als,initals,cos,{},decl)),scodeCmt); | ||
| 494 | |||
| 495 | case Absyn.PDER(functionName = path,vars = vars, comment=cmt) | ||
| 496 | algorithm | ||
| 497 | // fprintln(Flags.TRANSLATE, "translating pder( " + AbsynUtil.pathString(path) + ", vars)"); | ||
| 498 | 2 | scodeCmt := translateComment(cmt); | |
| 499 | 2 | then | |
| 500 | (SCode.PDER(path,vars),scodeCmt); | ||
| 501 | |||
| 502 | else | ||
| 503 | algorithm | ||
| 504 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{"AbsynToSCode.translateClassdef failed"}); | |
| 505 | ✗ | then | |
| 506 | fail(); | ||
| 507 | end match; | ||
| 508 | end translateClassdef; | ||
| 509 | |||
| 510 | protected function translateAlternativeExternalAnnotation | ||
| 511 | "Checks if the annotation for an external declaration is misplaced, i.e. | ||
| 512 | external \"C\"; annotation(Library=\"foo.lib\"); | ||
| 513 | instead of | ||
| 514 | external \"C\" annotation(Library=\"foo.lib\"); | ||
| 515 | " | ||
| 516 | input Option<SCode.ExternalDecl> decl; | ||
| 517 | input SCode.Comment comment; | ||
| 518 | input SourceInfo info; | ||
| 519 | output Option<SCode.ExternalDecl> outDecl; | ||
| 520 | protected | ||
| 521 | SCode.ExternalDecl ext_decl; | ||
| 522 | SCode.Annotation ann; | ||
| 523 | |||
| 524 | function whitelist_mod | ||
| 525 | input SCode.SubMod submod; | ||
| 526 | output Boolean keep; | ||
| 527 | algorithm | ||
| 528 | keep := match submod.ident | ||
| 529 | case "Library" then true; | ||
| 530 | case "Include" then true; | ||
| 531 | case "LibraryDirectory" then true; | ||
| 532 | case "SourceDirectory" then true; | ||
| 533 | case "License" then true; | ||
| 534 | else false; | ||
| 535 | end match; | ||
| 536 | end whitelist_mod; | ||
| 537 | algorithm | ||
| 538 | outDecl := match (decl, comment) | ||
| 539 | // The external declaration is missing an annotation but there is one on the function. | ||
| 540 | case (SOME(ext_decl as SCode.EXTERNALDECL(annotation_ = NONE())), SCode.COMMENT(annotation_ = SOME(ann))) | ||
| 541 | algorithm | ||
| 542 | // Filter out only the modifiers allowed on an external declaration. | ||
| 543 | 3070339 | ann.modification := SCodeUtil.filterSubMods(ann.modification, whitelist_mod); | |
| 544 | |||
| 545 | // If any matching modifiers were found, issue a warning and copy them to the external declaration. | ||
| 546 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3070334 times.
|
3070339 | if not SCodeUtil.isEmptyMod(ann.modification) then |
| 547 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | if Config.languageStandardAtLeast(Config.LanguageStandard._3_3) then |
| 548 | 5 | Error.addSourceMessage(Error.MISPLACED_EXTERNAL_ANNOTATION, {}, info); | |
| 549 | end if; | ||
| 550 | 5 | ext_decl.annotation_ := SOME(ann); | |
| 551 | end if; | ||
| 552 | then | ||
| 553 | SOME(ext_decl); | ||
| 554 | |||
| 555 | else decl; | ||
| 556 | end match; | ||
| 557 | end translateAlternativeExternalAnnotation; | ||
| 558 | |||
| 559 | protected function translateEnumlist | ||
| 560 | "Convert an EnumLiteral list to an Ident list. | ||
| 561 | Comments are lost." | ||
| 562 | input list<Absyn.EnumLiteral> inAbsynEnumLiteralLst; | ||
| 563 | output list<SCode.Enum> outEnumLst; | ||
| 564 | algorithm | ||
| 565 | outEnumLst := match inAbsynEnumLiteralLst | ||
| 566 | local | ||
| 567 | list<SCode.Enum> res; | ||
| 568 | String id; | ||
| 569 | Option<Absyn.Comment> cmtOpt; | ||
| 570 | SCode.Comment cmt; | ||
| 571 | list<Absyn.EnumLiteral> rest; | ||
| 572 | |||
| 573 | case {} then {}; | ||
| 574 | case Absyn.ENUMLITERAL(id, cmtOpt) :: rest | ||
| 575 | algorithm | ||
| 576 | 787088 | cmt := translateComment(cmtOpt); | |
| 577 | 787088 | res := translateEnumlist(rest); | |
| 578 | 787088 | then | |
| 579 | (SCode.ENUM(id, cmt) :: res); | ||
| 580 | end match; | ||
| 581 | end translateEnumlist; | ||
| 582 | |||
| 583 | public function translateClassdefElements | ||
| 584 | "Convert an Absyn.ClassPart list to an Element list." | ||
| 585 | input list<Absyn.ClassPart> inAbsynClassPartLst; | ||
| 586 | output list<SCode.Element> outElementLst; | ||
| 587 | algorithm | ||
| 588 | outElementLst := match inAbsynClassPartLst | ||
| 589 | local | ||
| 590 | list<SCode.Element> els,es_1; | ||
| 591 | list<Absyn.ElementItem> es; | ||
| 592 | list<Absyn.ClassPart> rest; | ||
| 593 | |||
| 594 | case {} then {}; | ||
| 595 | |||
| 596 | case Absyn.PUBLIC(contents = es) :: rest | ||
| 597 | algorithm | ||
| 598 | 6976826 | es_1 := translateEitemlist(es, SCode.PUBLIC()); | |
| 599 | 6976826 | els := translateClassdefElements(rest); | |
| 600 | 6976826 | els := listAppend(es_1, els); | |
| 601 | then | ||
| 602 | els; | ||
| 603 | |||
| 604 | case Absyn.PROTECTED(contents = es) :: rest | ||
| 605 | algorithm | ||
| 606 | 766606 | es_1 := translateEitemlist(es, SCode.PROTECTED()); | |
| 607 | 766606 | els := translateClassdefElements(rest); | |
| 608 | 766606 | els := listAppend(es_1, els); | |
| 609 | then | ||
| 610 | els; | ||
| 611 | |||
| 612 | case _ :: rest /* ignore all other than PUBLIC and PROTECTED, i.e. elements */ | ||
| 613 | 5626714 | then translateClassdefElements(rest); | |
| 614 | |||
| 615 | end match; | ||
| 616 | end translateClassdefElements; | ||
| 617 | |||
| 618 | protected function translateClassdefEquations | ||
| 619 | "Convert an Absyn.ClassPart list to an Equation list." | ||
| 620 | input list<Absyn.ClassPart> inAbsynClassPartLst; | ||
| 621 | output list<SCode.Equation> outEquationLst; | ||
| 622 | algorithm | ||
| 623 | outEquationLst := match inAbsynClassPartLst | ||
| 624 | local | ||
| 625 | list<SCode.Equation> eqs,eql_1,eqs_1; | ||
| 626 | list<Absyn.EquationItem> eql; | ||
| 627 | list<Absyn.ClassPart> rest; | ||
| 628 | case {} then {}; | ||
| 629 | case Absyn.EQUATIONS(contents = eql) :: rest | ||
| 630 | algorithm | ||
| 631 | 1070551 | eql_1 := translateEquations(eql, false); | |
| 632 | 1070551 | eqs := translateClassdefEquations(rest); | |
| 633 | 1070551 | eqs_1 := listAppend(eqs, eql_1); | |
| 634 | then | ||
| 635 | eqs_1; | ||
| 636 | case _ :: rest /* ignore everthing other than equations */ | ||
| 637 | algorithm | ||
| 638 | 12297673 | eqs := translateClassdefEquations(rest); | |
| 639 | then | ||
| 640 | eqs; | ||
| 641 | end match; | ||
| 642 | end translateClassdefEquations; | ||
| 643 | |||
| 644 | protected function translateClassdefInitialequations | ||
| 645 | "Convert an Absyn.ClassPart list to an initial Equation list." | ||
| 646 | input list<Absyn.ClassPart> inAbsynClassPartLst; | ||
| 647 | output list<SCode.Equation> outEquationLst; | ||
| 648 | algorithm | ||
| 649 | outEquationLst := match inAbsynClassPartLst | ||
| 650 | local | ||
| 651 | list<SCode.Equation> eqs,eql_1,eqs_1; | ||
| 652 | list<Absyn.EquationItem> eql; | ||
| 653 | list<Absyn.ClassPart> rest; | ||
| 654 | case {} then {}; | ||
| 655 | case Absyn.INITIALEQUATIONS(contents = eql) :: rest | ||
| 656 | algorithm | ||
| 657 | 104417 | eql_1 := translateEquations(eql, true); | |
| 658 | 104417 | eqs := translateClassdefInitialequations(rest); | |
| 659 | 104417 | eqs_1 := listAppend(eqs, eql_1); | |
| 660 | then | ||
| 661 | eqs_1; | ||
| 662 | case _ :: rest /* ignore everthing other than equations */ | ||
| 663 | algorithm | ||
| 664 | 13263807 | eqs := translateClassdefInitialequations(rest); | |
| 665 | then | ||
| 666 | eqs; | ||
| 667 | end match; | ||
| 668 | end translateClassdefInitialequations; | ||
| 669 | |||
| 670 | protected function translateClassdefAlgorithms | ||
| 671 | "Convert an Absyn.ClassPart list to an Algorithm list." | ||
| 672 | input list<Absyn.ClassPart> inAbsynClassPartLst; | ||
| 673 | output list<SCode.AlgorithmSection> outAlgorithmLst; | ||
| 674 | algorithm | ||
| 675 | outAlgorithmLst := match inAbsynClassPartLst | ||
| 676 | local | ||
| 677 | list<SCode.AlgorithmSection> als,als_1; | ||
| 678 | list<SCode.Statement> al_1; | ||
| 679 | list<Absyn.AlgorithmItem> al; | ||
| 680 | list<Absyn.ClassPart> rest; | ||
| 681 | case {} then {}; | ||
| 682 | case Absyn.ALGORITHMS(contents = al) :: rest | ||
| 683 | algorithm | ||
| 684 | 1112394 | al_1 := translateClassdefAlgorithmitems(al); | |
| 685 | 1112394 | als := translateClassdefAlgorithms(rest); | |
| 686 | 1112394 | als_1 := (SCode.ALGORITHM(al_1) :: als); | |
| 687 | then | ||
| 688 | als_1; | ||
| 689 | case _ :: rest /* ignore everthing other than algorithms */ | ||
| 690 | algorithm | ||
| 691 | 12255830 | als := translateClassdefAlgorithms(rest); | |
| 692 | then | ||
| 693 | als; | ||
| 694 | case _ | ||
| 695 | algorithm | ||
| 696 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 697 | ✗ | Debug.trace("- AbsynToSCode.translateClassdefAlgorithms failed\n"); | |
| 698 | ✗ | then fail(); | |
| 699 | end match; | ||
| 700 | end translateClassdefAlgorithms; | ||
| 701 | |||
| 702 | protected function translateClassdefConstraints | ||
| 703 | "Convert an Absyn.ClassPart list to an Constraint list." | ||
| 704 | input list<Absyn.ClassPart> inAbsynClassPartLst; | ||
| 705 | output list<SCode.ConstraintSection> outConstraintLst; | ||
| 706 | algorithm | ||
| 707 | outConstraintLst := match inAbsynClassPartLst | ||
| 708 | local | ||
| 709 | list<SCode.ConstraintSection> cos,cos_1; | ||
| 710 | list<Absyn.Exp> consts; | ||
| 711 | list<Absyn.ClassPart> rest; | ||
| 712 | case {} then {}; | ||
| 713 | case Absyn.CONSTRAINTS(contents = consts) :: rest | ||
| 714 | algorithm | ||
| 715 | 7 | cos := translateClassdefConstraints(rest); | |
| 716 | 7 | cos_1 := (SCode.CONSTRAINTS(consts) :: cos); | |
| 717 | then | ||
| 718 | cos_1; | ||
| 719 | case _ :: rest /* ignore everthing other than Constraints */ | ||
| 720 | algorithm | ||
| 721 | 13368217 | cos := translateClassdefConstraints(rest); | |
| 722 | then | ||
| 723 | cos; | ||
| 724 | case _ | ||
| 725 | algorithm | ||
| 726 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 727 | ✗ | Debug.trace("- AbsynToSCode.translateClassdefConstraints failed\n"); | |
| 728 | ✗ | then fail(); | |
| 729 | end match; | ||
| 730 | end translateClassdefConstraints; | ||
| 731 | |||
| 732 | protected function translateClassdefInitialalgorithms | ||
| 733 | "Convert an Absyn.ClassPart list to an initial Algorithm list." | ||
| 734 | input list<Absyn.ClassPart> inAbsynClassPartLst; | ||
| 735 | output list<SCode.AlgorithmSection> outAlgorithmLst; | ||
| 736 | algorithm | ||
| 737 | outAlgorithmLst := match inAbsynClassPartLst | ||
| 738 | local | ||
| 739 | list<SCode.AlgorithmSection> als,als_1; | ||
| 740 | list<SCode.Statement> stmts; | ||
| 741 | list<Absyn.AlgorithmItem> al; | ||
| 742 | list<Absyn.ClassPart> rest; | ||
| 743 | case {} then {}; | ||
| 744 | case Absyn.INITIALALGORITHMS(contents = al) :: rest | ||
| 745 | algorithm | ||
| 746 | 7337 | stmts := translateClassdefAlgorithmitems(al); | |
| 747 | 7337 | als := translateClassdefInitialalgorithms(rest); | |
| 748 | 7337 | als_1 := (SCode.ALGORITHM(stmts) :: als); | |
| 749 | then | ||
| 750 | als_1; | ||
| 751 | case _ :: rest /* ignore everthing other than algorithms */ | ||
| 752 | algorithm | ||
| 753 | 13360887 | als := translateClassdefInitialalgorithms(rest); | |
| 754 | then | ||
| 755 | als; | ||
| 756 | end match; | ||
| 757 | end translateClassdefInitialalgorithms; | ||
| 758 | |||
| 759 | public function translateClassdefAlgorithmitems | ||
| 760 | input list<Absyn.AlgorithmItem> inStatements; | ||
| 761 | output list<SCode.Statement> outStatements; | ||
| 762 | algorithm | ||
| 763 |
6/6✓ Branch 1 taken 554750 times.
✓ Branch 2 taken 5725373 times.
✓ Branch 3 taken 6280123 times.
✓ Branch 4 taken 2377884 times.
✓ Branch 5 taken 5725373 times.
✓ Branch 6 taken 2377884 times.
|
8658007 | outStatements := list(translateClassdefAlgorithmItem(stmt) for stmt guard AbsynUtil.isAlgorithmItem(stmt) in inStatements); |
| 764 | end translateClassdefAlgorithmitems; | ||
| 765 | |||
| 766 | protected function translateClassdefAlgorithmItem | ||
| 767 | "Translates an Absyn algorithm (statement) into SCode statement." | ||
| 768 | input Absyn.AlgorithmItem inAlgorithm; | ||
| 769 | output SCode.Statement outStatement; | ||
| 770 | protected | ||
| 771 | Option<Absyn.Comment> absynComment; | ||
| 772 | SCode.Comment comment; | ||
| 773 | SourceInfo info; | ||
| 774 | Absyn.Algorithm alg; | ||
| 775 | algorithm | ||
| 776 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5725373 times.
|
5725373 | Absyn.ALGORITHMITEM(algorithm_=alg, comment=absynComment, info=info) := inAlgorithm; |
| 777 | 5725373 | (comment, info) := translateCommentWithLineInfoChanges(absynComment, info); | |
| 778 | outStatement := match alg | ||
| 779 | local | ||
| 780 | list<SCode.Statement> body, else_body; | ||
| 781 | list<tuple<Absyn.Exp, list<SCode.Statement>>> branches; | ||
| 782 | String iter_name; | ||
| 783 | Option<Absyn.Exp> iter_range; | ||
| 784 | Absyn.Exp e1, e2, e3; | ||
| 785 | |||
| 786 | case Absyn.ALG_ASSIGN() | ||
| 787 | 4846476 | then SCode.ALG_ASSIGN(alg.assignComponent, alg.value, | |
| 788 | comment, info); | ||
| 789 | |||
| 790 | case Absyn.ALG_IF() | ||
| 791 | algorithm | ||
| 792 | 448990 | body := translateClassdefAlgorithmitems(alg.trueBranch); | |
| 793 | 448990 | else_body := translateClassdefAlgorithmitems(alg.elseBranch); | |
| 794 | 448990 | branches := translateAlgBranches(alg.elseIfAlgorithmBranch); | |
| 795 | 448990 | then | |
| 796 | SCode.ALG_IF(alg.ifExp, body, branches, else_body, comment, info); | ||
| 797 | |||
| 798 | case Absyn.ALG_FOR() | ||
| 799 | algorithm | ||
| 800 | 139256 | body := translateClassdefAlgorithmitems(alg.forBody); | |
| 801 | |||
| 802 | // Convert for-loops with multiple iterators into nested for-loops. | ||
| 803 |
2/2✓ Branch 1 taken 139258 times.
✓ Branch 2 taken 139256 times.
|
278514 | for i in listReverse(alg.iterators) loop |
| 804 | 139258 | (iter_name, iter_range) := translateIterator(i, info); | |
| 805 | 139258 | body := {SCode.ALG_FOR(iter_name, iter_range, body, comment, info)}; | |
| 806 | end for; | ||
| 807 | 139256 | then | |
| 808 | listHead(body); | ||
| 809 | |||
| 810 | case Absyn.ALG_PARFOR() | ||
| 811 | algorithm | ||
| 812 | ✗ | body := translateClassdefAlgorithmitems(alg.parforBody); | |
| 813 | |||
| 814 | // Convert for-loops with multiple iterators into nested for-loops. | ||
| 815 | ✗ | for i in listReverse(alg.iterators) loop | |
| 816 | ✗ | (iter_name, iter_range) := translateIterator(i, info); | |
| 817 | ✗ | body := {SCode.ALG_PARFOR(iter_name, iter_range, body, comment, info)}; | |
| 818 | end for; | ||
| 819 | ✗ | then | |
| 820 | listHead(body); | ||
| 821 | |||
| 822 | case Absyn.ALG_WHILE() | ||
| 823 | algorithm | ||
| 824 | 40332 | body := translateClassdefAlgorithmitems(alg.whileBody); | |
| 825 | 40332 | then | |
| 826 | SCode.ALG_WHILE(alg.boolExpr, body, comment, info); | ||
| 827 | |||
| 828 | case Absyn.ALG_WHEN_A() | ||
| 829 | algorithm | ||
| 830 | 10054 | branches := translateAlgBranches((alg.boolExpr, alg.whenBody) | |
| 831 | :: alg.elseWhenAlgorithmBranch); | ||
| 832 | 10054 | then | |
| 833 | SCode.ALG_WHEN_A(branches, comment, info); | ||
| 834 | |||
| 835 | // assert(condition, message) | ||
| 836 | case Absyn.ALG_NORETCALL(functionCall = Absyn.CREF_IDENT(name = "assert"), | ||
| 837 | functionArgs = Absyn.FUNCTIONARGS(args = {e1, e2}, argNames = {})) | ||
| 838 | 114938 | then SCode.ALG_ASSERT(e1, e2, ASSERTION_LEVEL_ERROR, comment, info); | |
| 839 | |||
| 840 | // assert(condition, message, level) | ||
| 841 | case Absyn.ALG_NORETCALL(functionCall = Absyn.CREF_IDENT(name = "assert"), | ||
| 842 | functionArgs = Absyn.FUNCTIONARGS(args = {e1, e2, e3}, argNames = {})) | ||
| 843 | 459 | then SCode.ALG_ASSERT(e1, e2, e3, comment, info); | |
| 844 | |||
| 845 | // assert(condition, message, level = arg) | ||
| 846 | case Absyn.ALG_NORETCALL(functionCall = Absyn.CREF_IDENT(name = "assert"), | ||
| 847 | functionArgs = Absyn.FUNCTIONARGS(args = {e1, e2}, | ||
| 848 | argNames = {Absyn.NAMEDARG("level", e3)})) | ||
| 849 | 1496 | then SCode.ALG_ASSERT(e1, e2, e3, comment, info); | |
| 850 | |||
| 851 | case Absyn.ALG_NORETCALL(functionCall = Absyn.CREF_IDENT(name = "terminate"), | ||
| 852 | functionArgs = Absyn.FUNCTIONARGS(args = {e1}, argNames = {})) | ||
| 853 | 63 | then SCode.ALG_TERMINATE(e1, comment, info); | |
| 854 | |||
| 855 | case Absyn.ALG_NORETCALL(functionCall = Absyn.CREF_IDENT(name = "reinit"), | ||
| 856 | functionArgs = Absyn.FUNCTIONARGS(args = {e1, e2}, argNames = {})) | ||
| 857 | 25 | then SCode.ALG_REINIT(e1, e2, comment, info); | |
| 858 | |||
| 859 | case Absyn.ALG_NORETCALL() | ||
| 860 | algorithm | ||
| 861 | 103195 | e1 := Absyn.CALL(alg.functionCall, alg.functionArgs, {}); | |
| 862 | 103195 | then | |
| 863 | SCode.ALG_NORETCALL(e1, comment, info); | ||
| 864 | |||
| 865 | case Absyn.ALG_FAILURE() | ||
| 866 | algorithm | ||
| 867 | 20 | body := translateClassdefAlgorithmitems(alg.equ); | |
| 868 | 20 | then | |
| 869 | SCode.ALG_FAILURE(body, comment, info); | ||
| 870 | |||
| 871 | case Absyn.ALG_TRY() | ||
| 872 | algorithm | ||
| 873 | 2093 | body := translateClassdefAlgorithmitems(alg.body); | |
| 874 | 2093 | else_body := translateClassdefAlgorithmitems(alg.elseBody); | |
| 875 | 2093 | then | |
| 876 | SCode.ALG_TRY(body, else_body, comment, info); | ||
| 877 | |||
| 878 | 9652 | case Absyn.ALG_RETURN() then SCode.ALG_RETURN(comment, info); | |
| 879 | 8233 | case Absyn.ALG_BREAK() then SCode.ALG_BREAK(comment, info); | |
| 880 | 91 | case Absyn.ALG_CONTINUE() then SCode.ALG_CONTINUE(comment, info); | |
| 881 | |||
| 882 | end match; | ||
| 883 | end translateClassdefAlgorithmItem; | ||
| 884 | |||
| 885 | protected function translateAlgBranches | ||
| 886 | "Translates the elseif or elsewhen branches from Absyn to SCode form." | ||
| 887 | input list<tuple<Absyn.Exp, list<Absyn.AlgorithmItem>>> inBranches; | ||
| 888 | output list<tuple<Absyn.Exp, list<SCode.Statement>>> outBranches; | ||
| 889 | protected | ||
| 890 | Absyn.Exp condition; | ||
| 891 | list<Absyn.AlgorithmItem> body; | ||
| 892 | algorithm | ||
| 893 |
4/4✓ Branch 0 taken 171215 times.
✓ Branch 1 taken 459044 times.
✓ Branch 2 taken 171215 times.
✓ Branch 3 taken 459044 times.
|
630259 | outBranches := list( |
| 894 | match branch case (condition, body) | ||
| 895 | 171215 | then (condition, translateClassdefAlgorithmitems(body)); | |
| 896 | end match | ||
| 897 | for branch in inBranches); | ||
| 898 | end translateAlgBranches; | ||
| 899 | |||
| 900 | protected function translateClassdefExternaldecls | ||
| 901 | "Converts an Absyn.ClassPart list to an SCode.ExternalDecl option. | ||
| 902 | The list should only contain one external declaration, so pick the first one." | ||
| 903 | input list<Absyn.ClassPart> inAbsynClassPartLst; | ||
| 904 | output Option<SCode.ExternalDecl> outAbsynExternalDeclOption; | ||
| 905 | algorithm | ||
| 906 | outAbsynExternalDeclOption := match inAbsynClassPartLst | ||
| 907 | local | ||
| 908 | Option<SCode.ExternalDecl> res; | ||
| 909 | list<Absyn.ClassPart> rest; | ||
| 910 | Option<SCode.Ident> fn_name; | ||
| 911 | Option<String> lang; | ||
| 912 | Option<Absyn.ComponentRef> output_; | ||
| 913 | list<Absyn.Exp> args; | ||
| 914 | Option<Absyn.Annotation> aann; | ||
| 915 | Option<SCode.Annotation> sann; | ||
| 916 | |||
| 917 | case Absyn.EXTERNAL(externalDecl = | ||
| 918 | Absyn.EXTERNALDECL(fn_name, lang, output_, args, aann)) :: _ | ||
| 919 | algorithm | ||
| 920 | 3332008 | sann := translateAnnotationOpt(aann); | |
| 921 | 3332008 | then SOME(SCode.EXTERNALDECL(fn_name, lang, output_, args, sann)); | |
| 922 | case _ :: rest | ||
| 923 | algorithm | ||
| 924 | 10036216 | res := translateClassdefExternaldecls(rest); | |
| 925 | then | ||
| 926 | res; | ||
| 927 | case {} then NONE(); | ||
| 928 | end match; | ||
| 929 | end translateClassdefExternaldecls; | ||
| 930 | |||
| 931 | public function translateEitemlist | ||
| 932 | "This function converts a list of Absyn.ElementItem to a list of SCode.Element. | ||
| 933 | The boolean argument flags whether the elements are protected. | ||
| 934 | Annotations are not translated, i.e. they are removed when converting to SCode." | ||
| 935 | input list<Absyn.ElementItem> inAbsynElementItemLst; | ||
| 936 | input SCode.Visibility inVisibility; | ||
| 937 | output list<SCode.Element> outElementLst; | ||
| 938 | protected | ||
| 939 | list<SCode.Element> l = {}; | ||
| 940 | list<Absyn.ElementItem> es = inAbsynElementItemLst; | ||
| 941 | Absyn.ElementItem ei; | ||
| 942 | Absyn.Element e; | ||
| 943 | algorithm | ||
| 944 |
2/2✓ Branch 0 taken 41126437 times.
✓ Branch 1 taken 7744399 times.
|
48870836 | for ei in es loop |
| 945 | () := match ei | ||
| 946 | local | ||
| 947 | list<SCode.Element> e_1; | ||
| 948 | case Absyn.ELEMENTITEM(element = e) | ||
| 949 | algorithm | ||
| 950 | // fprintln(Flags.TRANSLATE, "translating element: " + Dump.unparseElementStr(1, e)); | ||
| 951 | 40144533 | e_1 := translateElement(e, inVisibility); | |
| 952 | 40144533 | l := List.append_reverse(e_1, l); | |
| 953 | then (); | ||
| 954 | else (); | ||
| 955 | end match; | ||
| 956 | end for; | ||
| 957 | 7744399 | outElementLst := Dangerous.listReverseInPlace(l); | |
| 958 | end translateEitemlist; | ||
| 959 | |||
| 960 | // stefan | ||
| 961 | public function translateAnnotation | ||
| 962 | "translates an Absyn.Annotation into an SCode.Annotation" | ||
| 963 | input Absyn.Annotation inAnnotation; | ||
| 964 | output Option<SCode.Annotation> outAnnotation; | ||
| 965 | algorithm | ||
| 966 | outAnnotation := match inAnnotation | ||
| 967 | local | ||
| 968 | list<Absyn.ElementArg> args; | ||
| 969 | SCode.Mod m; | ||
| 970 | |||
| 971 | case Absyn.ANNOTATION(elementArgs = {}) then NONE(); | ||
| 972 | |||
| 973 | case Absyn.ANNOTATION(elementArgs = args) | ||
| 974 | algorithm | ||
| 975 | // Keep empty modifiers since they might have meaning in annotations, e.g. annotation(Dialog()). | ||
| 976 | 35028602 | m := translateMod(SOME(Absyn.CLASSMOD(args,Absyn.NOMOD())), SCode.NOT_FINAL(), SCode.NOT_EACH(), NONE(), Absyn.dummyInfo, keepEmpty = true); | |
| 977 | |||
| 978 |
1/2✓ Branch 1 taken 17514301 times.
✗ Branch 2 not taken.
|
17514301 | then |
| 979 | if SCodeUtil.isEmptyMod(m) then NONE() else SOME(SCode.ANNOTATION(m)); | ||
| 980 | |||
| 981 | end match; | ||
| 982 | end translateAnnotation; | ||
| 983 | |||
| 984 | public function translateAnnotationOpt | ||
| 985 | input Option<Absyn.Annotation> absynAnnotation; | ||
| 986 | output Option<SCode.Annotation> scodeAnnotation; | ||
| 987 | algorithm | ||
| 988 | scodeAnnotation := match absynAnnotation | ||
| 989 | local | ||
| 990 | Absyn.Annotation ann; | ||
| 991 | |||
| 992 | 11775853 | case SOME(ann) then translateAnnotation(ann); | |
| 993 | else NONE(); | ||
| 994 | end match; | ||
| 995 | end translateAnnotationOpt; | ||
| 996 | |||
| 997 | public function translateElement | ||
| 998 | "This function converts an Absyn.Element to a list of SCode.Element. | ||
| 999 | The original element may declare several components at once, and | ||
| 1000 | those are separated to several declarations in the result." | ||
| 1001 | input Absyn.Element inElement; | ||
| 1002 | input SCode.Visibility inVisibility; | ||
| 1003 | output list<SCode.Element> outElementLst; | ||
| 1004 | algorithm | ||
| 1005 | outElementLst := match (inElement,inVisibility) | ||
| 1006 | local | ||
| 1007 | list<SCode.Element> es; | ||
| 1008 | Boolean f; | ||
| 1009 | Option<Absyn.RedeclareKeywords> repl; | ||
| 1010 | Absyn.ElementSpec s; | ||
| 1011 | Absyn.InnerOuter io; | ||
| 1012 | SourceInfo info; | ||
| 1013 | Option<Absyn.ConstrainClass> cc; | ||
| 1014 | Option<String> expOpt; | ||
| 1015 | Option<Real> weightOpt; | ||
| 1016 | list<Absyn.NamedArg> args; | ||
| 1017 | String name; | ||
| 1018 | SCode.Visibility vis; | ||
| 1019 | |||
| 1020 | case (Absyn.ELEMENT(constrainClass = cc,finalPrefix = f,innerOuter = io, redeclareKeywords = repl,specification = s,info = info),vis) | ||
| 1021 | algorithm | ||
| 1022 | 40144539 | es := translateElementspec(cc, f, io, repl, vis, s, info); | |
| 1023 | then | ||
| 1024 | es; | ||
| 1025 | |||
| 1026 | case(Absyn.DEFINEUNIT(name, args, info), vis) | ||
| 1027 | algorithm | ||
| 1028 | ✗ | expOpt := translateDefineunitParam(args,"exp"); | |
| 1029 | ✗ | weightOpt := translateDefineunitParam2(args,"weight"); | |
| 1030 | ✗ | then {SCode.DEFINEUNIT(name,vis,expOpt,weightOpt,info)}; | |
| 1031 | end match; | ||
| 1032 | end translateElement; | ||
| 1033 | |||
| 1034 | protected function translateDefineunitParam " help function to translateElement" | ||
| 1035 | input list<Absyn.NamedArg> inArgs; | ||
| 1036 | input String inArg; | ||
| 1037 | output Option<String> expOpt; | ||
| 1038 | algorithm | ||
| 1039 | expOpt := match (inArgs,inArg) | ||
| 1040 | local | ||
| 1041 | String str,name, arg; | ||
| 1042 | list<Absyn.NamedArg> args; | ||
| 1043 | |||
| 1044 | case(Absyn.NAMEDARG(name,Absyn.STRING(str))::_,arg) guard name == arg | ||
| 1045 | then SOME(str); | ||
| 1046 | case({},_) then NONE(); | ||
| 1047 | ✗ | case(_::args,arg) then translateDefineunitParam(args,arg); | |
| 1048 | end match; | ||
| 1049 | end translateDefineunitParam; | ||
| 1050 | |||
| 1051 | protected function translateDefineunitParam2 " help function to translateElement" | ||
| 1052 | input list<Absyn.NamedArg> inArgs; | ||
| 1053 | input String inArg; | ||
| 1054 | output Option<Real> weightOpt; | ||
| 1055 | algorithm | ||
| 1056 | weightOpt := match (inArgs,inArg) | ||
| 1057 | local | ||
| 1058 | String name, arg, s; | ||
| 1059 | Real r; | ||
| 1060 | list<Absyn.NamedArg> args; | ||
| 1061 | |||
| 1062 | case (Absyn.NAMEDARG(name,Absyn.REAL(s))::_,arg) guard name == arg | ||
| 1063 | algorithm | ||
| 1064 | ✗ | r := stringReal(s); | |
| 1065 | ✗ | then SOME(r); | |
| 1066 | case({},_) then NONE(); | ||
| 1067 | ✗ | case(_::args,arg) then translateDefineunitParam2(args,arg); | |
| 1068 | end match; | ||
| 1069 | end translateDefineunitParam2; | ||
| 1070 | |||
| 1071 | protected function translateElementspec | ||
| 1072 | "This function turns an Absyn.ElementSpec to a list of SCode.Element. | ||
| 1073 | The boolean arguments say if the element is final and protected, respectively." | ||
| 1074 | input Option<Absyn.ConstrainClass> cc; | ||
| 1075 | input Boolean finalPrefix; | ||
| 1076 | input Absyn.InnerOuter io; | ||
| 1077 | input Option<Absyn.RedeclareKeywords> inRedeclareKeywords; | ||
| 1078 | input SCode.Visibility inVisibility; | ||
| 1079 | input Absyn.ElementSpec inElementSpec4; | ||
| 1080 | input SourceInfo inInfo; | ||
| 1081 | output list<SCode.Element> outElementLst; | ||
| 1082 | algorithm | ||
| 1083 | outElementLst := match (inRedeclareKeywords, inVisibility, inElementSpec4, inInfo) | ||
| 1084 | local | ||
| 1085 | SCode.ClassDef de_1; | ||
| 1086 | SCode.Restriction re_1; | ||
| 1087 | Boolean rp,pa,e,repl_1,fl,st,redecl; | ||
| 1088 | Option<Absyn.RedeclareKeywords> repl; | ||
| 1089 | Absyn.Class cl; | ||
| 1090 | String n; | ||
| 1091 | Absyn.Restriction re; | ||
| 1092 | Absyn.ClassDef de; | ||
| 1093 | SCode.Mod mod; | ||
| 1094 | list<Absyn.ElementArg> args; | ||
| 1095 | list<SCode.Element> xs_1; | ||
| 1096 | SCode.Parallelism prl1; | ||
| 1097 | SCode.Variability var1; | ||
| 1098 | list<SCode.Subscript> tot_dim,ad,d; | ||
| 1099 | Absyn.Direction di; | ||
| 1100 | Absyn.IsField isf; | ||
| 1101 | Absyn.TypeSpec t; | ||
| 1102 | Option<Absyn.Modification> m; | ||
| 1103 | Option<Absyn.Comment> comment; | ||
| 1104 | SCode.Comment cmt; | ||
| 1105 | Absyn.Import imp; | ||
| 1106 | Option<Absyn.Exp> cond; | ||
| 1107 | Absyn.Path path; | ||
| 1108 | Absyn.Annotation absann; | ||
| 1109 | Option<SCode.Annotation> ann; | ||
| 1110 | Absyn.Variability variability; | ||
| 1111 | Absyn.Parallelism parallelism; | ||
| 1112 | SourceInfo i,info; | ||
| 1113 | SCode.Element cls; | ||
| 1114 | SCode.Redeclare sRed; | ||
| 1115 | SCode.Final sFin; | ||
| 1116 | SCode.Replaceable sRep; | ||
| 1117 | SCode.Encapsulated sEnc; | ||
| 1118 | SCode.Partial sPar; | ||
| 1119 | SCode.Visibility vis; | ||
| 1120 | SCode.ConnectorType ct; | ||
| 1121 | SCode.Prefixes prefixes; | ||
| 1122 | Option<SCode.ConstrainClass> scc; | ||
| 1123 | |||
| 1124 | |||
| 1125 | case (repl, vis, Absyn.CLASSDEF(replaceable_ = rp, class_ = (Absyn.CLASS(name = n,partialPrefix = pa,encapsulatedPrefix = e,restriction = Absyn.R_OPERATOR(),body = de,info = i))), _) | ||
| 1126 | algorithm | ||
| 1127 | 1922 | (de_1,cmt) := translateOperatorDef(de,n,i); | |
| 1128 | 1922 | (_, redecl) := translateRedeclarekeywords(repl); | |
| 1129 | 1922 | sRed := SCodeUtil.boolRedeclare(redecl); | |
| 1130 | 1922 | sFin := SCodeUtil.boolFinal(finalPrefix); | |
| 1131 | 1922 | scc := translateConstrainClass(cc); | |
| 1132 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1922 times.
|
1922 | sRep := if rp then SCode.REPLACEABLE(scc) else SCode.NOT_REPLACEABLE(); |
| 1133 | 1922 | sEnc := SCodeUtil.boolEncapsulated(e); | |
| 1134 | 1922 | sPar := SCodeUtil.boolPartial(pa); | |
| 1135 | 1922 | cls := SCode.CLASS( | |
| 1136 | n, | ||
| 1137 | SCode.PREFIXES(vis,sRed,sFin,io,sRep), | ||
| 1138 | sEnc, sPar, SCode.R_OPERATOR(), de_1, cmt, i); | ||
| 1139 | then | ||
| 1140 | {cls}; | ||
| 1141 | |||
| 1142 | |||
| 1143 | case (repl, vis, Absyn.CLASSDEF(replaceable_ = rp, class_ = (cl as Absyn.CLASS(name = n,partialPrefix = pa,encapsulatedPrefix = e,restriction = re,body = de,info = i))), _) | ||
| 1144 | algorithm | ||
| 1145 | // fprintln(Flags.TRANSLATE, "translating local class: " + n); | ||
| 1146 | 7026248 | re_1 := translateRestriction(cl, re); // uniontype will not get translated! | |
| 1147 | 7026248 | (de_1,cmt) := translateClassdef(de,i,re_1); | |
| 1148 | 7026248 | (_, redecl) := translateRedeclarekeywords(repl); | |
| 1149 | 7026248 | sRed := SCodeUtil.boolRedeclare(redecl); | |
| 1150 | 7026248 | sFin := SCodeUtil.boolFinal(finalPrefix); | |
| 1151 | 7026248 | scc := translateConstrainClass(cc); | |
| 1152 |
2/2✓ Branch 0 taken 109222 times.
✓ Branch 1 taken 6917026 times.
|
7026248 | sRep := if rp then SCode.REPLACEABLE(scc) else SCode.NOT_REPLACEABLE(); |
| 1153 | 7026248 | sEnc := SCodeUtil.boolEncapsulated(e); | |
| 1154 | 7026248 | sPar := SCodeUtil.boolPartial(pa); | |
| 1155 | 7026248 | cls := SCode.CLASS( | |
| 1156 | n, | ||
| 1157 | SCode.PREFIXES(vis,sRed,sFin,io,sRep), | ||
| 1158 | sEnc, sPar, re_1, de_1, cmt, i); | ||
| 1159 | then | ||
| 1160 | {cls}; | ||
| 1161 | |||
| 1162 | case (_, vis, Absyn.EXTENDS(path = path,elementArg = args,annotationOpt = NONE()), info) | ||
| 1163 | algorithm | ||
| 1164 | // fprintln(Flags.TRANSLATE, "translating extends: " + AbsynUtil.pathString(n)); | ||
| 1165 | 5103574 | mod := translateMod(SOME(Absyn.CLASSMOD(args,Absyn.NOMOD())), SCode.NOT_FINAL(), SCode.NOT_EACH(), NONE(), Absyn.dummyInfo); | |
| 1166 | 2551787 | then | |
| 1167 | {SCode.EXTENDS(path,vis,mod,NONE(),info)}; | ||
| 1168 | |||
| 1169 | case (_, vis, Absyn.EXTENDS(path = path,elementArg = args,annotationOpt = SOME(absann)), info) | ||
| 1170 | algorithm | ||
| 1171 | // fprintln(Flags.TRANSLATE, "translating extends: " + AbsynUtil.pathString(n)); | ||
| 1172 | 2016 | mod := translateMod(SOME(Absyn.CLASSMOD(args,Absyn.NOMOD())), SCode.NOT_FINAL(), SCode.NOT_EACH(), NONE(), Absyn.dummyInfo); | |
| 1173 | 1008 | ann := translateAnnotation(absann); | |
| 1174 | 1008 | then | |
| 1175 | {SCode.EXTENDS(path,vis,mod,ann,info)}; | ||
| 1176 | |||
| 1177 | case (_, _, Absyn.COMPONENTS(components = {}), _) then {}; | ||
| 1178 | |||
| 1179 | case (repl, vis, Absyn.COMPONENTS(attributes = | ||
| 1180 | (Absyn.ATTR(flowPrefix = fl,streamPrefix=st,parallelism=parallelism,variability = variability,direction = di,isField = isf,arrayDim = ad)), typeSpec = t), info) | ||
| 1181 | algorithm | ||
| 1182 | xs_1 := {}; | ||
| 1183 |
2/2✓ Branch 0 taken 30441352 times.
✓ Branch 1 taken 30284306 times.
|
60725658 | for comp in inElementSpec4.components loop |
| 1184 | 30441352 | Absyn.COMPONENTITEM(component=Absyn.COMPONENT(name = n,arrayDim = d,modification = m),comment = comment, condition=cond) := comp; | |
| 1185 | // TODO: Improve performance by iterating over all elements at once instead of creating a new Absyn.COMPONENTS in each step... | ||
| 1186 | 30441352 | checkTypeSpec(t,info); | |
| 1187 | // fprintln(Flags.TRANSLATE, "translating component: " + n + " final: " + SCodeUtil.finalStr(SCodeUtil.boolFinal(finalPrefix))); | ||
| 1188 | 30441352 | setHasInnerOuterDefinitionsHandler(io); // signal the external flag that we have inner/outer definitions | |
| 1189 | 30441352 | setHasStreamConnectorsHandler(st); // signal the external flag that we have stream connectors | |
| 1190 | 30441352 | mod := translateMod(m, SCode.NOT_FINAL(), SCode.NOT_EACH(), NONE(), info); | |
| 1191 | 30441352 | prl1 := translateParallelism(parallelism); | |
| 1192 | 30441352 | var1 := translateVariability(variability); | |
| 1193 | // PR. This adds the arraydimension that may be specified together with the type of the component. | ||
| 1194 | 30441352 | tot_dim := listAppend(d, ad); | |
| 1195 | 30441352 | (repl_1, redecl) := translateRedeclarekeywords(repl); | |
| 1196 | 30441352 | (cmt,info) := translateCommentWithLineInfoChanges(comment,info); | |
| 1197 | 30441352 | sFin := SCodeUtil.boolFinal(finalPrefix); | |
| 1198 | 30441352 | sRed := SCodeUtil.boolRedeclare(redecl); | |
| 1199 | 30441352 | scc := translateConstrainClass(cc); | |
| 1200 |
2/2✓ Branch 0 taken 18770 times.
✓ Branch 1 taken 30422582 times.
|
30441352 | sRep := if repl_1 then SCode.REPLACEABLE(scc) else SCode.NOT_REPLACEABLE(); |
| 1201 | 30441352 | ct := translateConnectorType(fl, st); | |
| 1202 | 30441352 | prefixes := SCode.PREFIXES(vis,sRed,sFin,io,sRep); | |
| 1203 | xs_1 := match di | ||
| 1204 | local | ||
| 1205 | SCode.Attributes attr1,attr2; | ||
| 1206 | SCode.Mod mod2; | ||
| 1207 | String inName; | ||
| 1208 | case Absyn.INPUT_OUTPUT() guard not Flags.isSet(Flags.SKIP_INPUT_OUTPUT_SYNTACTIC_SUGAR) | ||
| 1209 | algorithm | ||
| 1210 | 22669 | inName := "$in_"+n; | |
| 1211 | 22669 | attr1 := SCode.ATTR(tot_dim,ct,prl1,var1,Absyn.INPUT(),isf); | |
| 1212 | 22669 | attr2 := SCode.ATTR(tot_dim,ct,prl1,var1,Absyn.OUTPUT(),isf); | |
| 1213 | 22669 | mod2 := SCode.MOD(SCode.FINAL(), SCode.NOT_EACH(), {}, SOME(Absyn.CREF(Absyn.CREF_IDENT(inName,{}))), NONE(), info); | |
| 1214 | 22669 | then SCode.COMPONENT(n,prefixes,attr2,t,mod2,cmt,cond,info) :: SCode.COMPONENT(inName,prefixes,attr1,t,mod,cmt,cond,info) :: xs_1; | |
| 1215 | 30418683 | else SCode.COMPONENT(n,prefixes,SCode.ATTR(tot_dim,ct,prl1,var1,di,isf),t,mod,cmt,cond,info) :: xs_1; | |
| 1216 | end match; | ||
| 1217 | end for; | ||
| 1218 | 30284306 | xs_1 := Dangerous.listReverseInPlace(xs_1); | |
| 1219 | then xs_1; | ||
| 1220 | case (_, vis, Absyn.IMPORT(import_ = imp, info = info), _) | ||
| 1221 | algorithm | ||
| 1222 | // fprintln(Flags.TRANSLATE, "translating import: " + Dump.unparseImportStr(imp)); | ||
| 1223 | 561882 | xs_1 := translateImports(imp,vis,info); | |
| 1224 | then | ||
| 1225 | xs_1; | ||
| 1226 | |||
| 1227 | else | ||
| 1228 | algorithm | ||
| 1229 | ✗ | Error.addMessage(Error.INTERNAL_ERROR, {"AbsynToSCode.translateElementspec failed"}); | |
| 1230 | ✗ | then fail(); | |
| 1231 | end match; | ||
| 1232 | end translateElementspec; | ||
| 1233 | |||
| 1234 | protected function translateImports "Used to handle group imports, i.e. A.B.C.{x=a,b}" | ||
| 1235 | input Absyn.Import imp; | ||
| 1236 | input SCode.Visibility visibility; | ||
| 1237 | input SourceInfo info; | ||
| 1238 | output list<SCode.Element> elts; | ||
| 1239 | algorithm | ||
| 1240 | elts := match imp | ||
| 1241 | local | ||
| 1242 | String name; | ||
| 1243 | Absyn.Path p; | ||
| 1244 | list<Absyn.GroupImport> groups; | ||
| 1245 | |||
| 1246 | /* Maybe these should give warnings? I don't know. See https://trac.modelica.org/Modelica/ticket/955 */ | ||
| 1247 | case Absyn.NAMED_IMPORT(name,Absyn.FULLYQUALIFIED(p)) | ||
| 1248 | ✗ | then translateImports(Absyn.NAMED_IMPORT(name,p),visibility,info); | |
| 1249 | case Absyn.QUAL_IMPORT(Absyn.FULLYQUALIFIED(p)) | ||
| 1250 | ✗ | then translateImports(Absyn.QUAL_IMPORT(p),visibility,info); | |
| 1251 | case Absyn.UNQUAL_IMPORT(Absyn.FULLYQUALIFIED(p)) | ||
| 1252 | ✗ | then translateImports(Absyn.UNQUAL_IMPORT(p),visibility,info); | |
| 1253 | |||
| 1254 | case Absyn.GROUP_IMPORT(prefix=p,groups=groups) | ||
| 1255 | 6164 | then List.map3(groups, translateGroupImport, p, visibility, info); | |
| 1256 | 555718 | else {SCode.IMPORT(imp, visibility, info)}; | |
| 1257 | end match; | ||
| 1258 | end translateImports; | ||
| 1259 | |||
| 1260 | protected function translateGroupImport "Used to handle group imports, i.e. A.B.C.{x=a,b}" | ||
| 1261 | input Absyn.GroupImport gimp; | ||
| 1262 | input Absyn.Path prefix; | ||
| 1263 | input SCode.Visibility visibility; | ||
| 1264 | input SourceInfo info; | ||
| 1265 | output SCode.Element elt; | ||
| 1266 | algorithm | ||
| 1267 | elt := match (gimp, visibility) | ||
| 1268 | local | ||
| 1269 | String name,rename; | ||
| 1270 | Absyn.Path path; | ||
| 1271 | SCode.Visibility vis; | ||
| 1272 | |||
| 1273 | case (Absyn.GROUP_IMPORT_NAME(name=name), vis) | ||
| 1274 | algorithm | ||
| 1275 | 18549 | path := AbsynUtil.joinPaths(prefix,Absyn.IDENT(name)); | |
| 1276 | 18549 | then SCode.IMPORT(Absyn.QUAL_IMPORT(path),vis,info); | |
| 1277 | case (Absyn.GROUP_IMPORT_RENAME(rename=rename,name=name), vis) | ||
| 1278 | algorithm | ||
| 1279 | ✗ | path := AbsynUtil.joinPaths(prefix,Absyn.IDENT(name)); | |
| 1280 | ✗ | then SCode.IMPORT(Absyn.NAMED_IMPORT(rename,path),vis,info); | |
| 1281 | end match; | ||
| 1282 | end translateGroupImport; | ||
| 1283 | |||
| 1284 | protected function setHasInnerOuterDefinitionsHandler | ||
| 1285 | "@author: adrpo | ||
| 1286 | This function will set the external flag that signals | ||
| 1287 | that a model has inner/outer component definitions" | ||
| 1288 | input Absyn.InnerOuter io; | ||
| 1289 | algorithm | ||
| 1290 | () := match io | ||
| 1291 | // no inner outer! | ||
| 1292 | case Absyn.NOT_INNER_OUTER() then (); | ||
| 1293 | // has inner, outer or innerouter components | ||
| 1294 | else | ||
| 1295 | algorithm | ||
| 1296 | 63081 | System.setHasInnerOuterDefinitions(true); | |
| 1297 | then (); | ||
| 1298 | end match; | ||
| 1299 | end setHasInnerOuterDefinitionsHandler; | ||
| 1300 | |||
| 1301 | protected function setHasStreamConnectorsHandler | ||
| 1302 | "@author: adrpo | ||
| 1303 | This function will set the external flag that signals | ||
| 1304 | that a model has stream connectors" | ||
| 1305 | input Boolean streamPrefix; | ||
| 1306 | algorithm | ||
| 1307 | () := match streamPrefix | ||
| 1308 | // no stream prefix | ||
| 1309 | case false then (); | ||
| 1310 | // has stream prefix | ||
| 1311 | case true | ||
| 1312 | algorithm | ||
| 1313 | 1512 | System.setHasStreamConnectors(true); | |
| 1314 | then (); | ||
| 1315 | end match; | ||
| 1316 | end setHasStreamConnectorsHandler; | ||
| 1317 | |||
| 1318 | protected function translateRedeclarekeywords | ||
| 1319 | "author: PA | ||
| 1320 | For now, translate to bool, replaceable." | ||
| 1321 | input Option<Absyn.RedeclareKeywords> inRedeclKeywords; | ||
| 1322 | output Boolean outIsReplaceable; | ||
| 1323 | output Boolean outIsRedeclared; | ||
| 1324 | algorithm | ||
| 1325 | (outIsReplaceable, outIsRedeclared) := match inRedeclKeywords | ||
| 1326 | case SOME(Absyn.REDECLARE()) then (false, true); | ||
| 1327 | case SOME(Absyn.REPLACEABLE()) then (true, false); | ||
| 1328 | case SOME(Absyn.REDECLARE_REPLACEABLE()) then (true, true); | ||
| 1329 | else (false, false); | ||
| 1330 | end match; | ||
| 1331 | end translateRedeclarekeywords; | ||
| 1332 | |||
| 1333 | protected function translateConstrainClass | ||
| 1334 | input Option<Absyn.ConstrainClass> inConstrainClass; | ||
| 1335 | output Option<SCode.ConstrainClass> outConstrainClass; | ||
| 1336 | algorithm | ||
| 1337 | outConstrainClass := match inConstrainClass | ||
| 1338 | local | ||
| 1339 | Absyn.Path cc_path; | ||
| 1340 | list<Absyn.ElementArg> eltargs; | ||
| 1341 | Option<Absyn.Comment> cmt; | ||
| 1342 | SCode.Comment cc_cmt; | ||
| 1343 | Absyn.Modification mod; | ||
| 1344 | SCode.Mod cc_mod; | ||
| 1345 | |||
| 1346 | case SOME(Absyn.CONSTRAINCLASS(elementSpec = | ||
| 1347 | Absyn.EXTENDS(path = cc_path, elementArg = eltargs), comment = cmt)) | ||
| 1348 | algorithm | ||
| 1349 | 19520 | mod := Absyn.CLASSMOD(eltargs, Absyn.NOMOD()); | |
| 1350 | 19520 | cc_mod := translateMod(SOME(mod), SCode.NOT_FINAL(), SCode.NOT_EACH(), NONE(), Absyn.dummyInfo); | |
| 1351 | 19520 | cc_cmt := translateComment(cmt); | |
| 1352 | 19520 | then | |
| 1353 | SOME(SCode.CONSTRAINCLASS(cc_path, cc_mod, cc_cmt)); | ||
| 1354 | |||
| 1355 | else NONE(); | ||
| 1356 | end match; | ||
| 1357 | end translateConstrainClass; | ||
| 1358 | |||
| 1359 | protected function translateParallelism | ||
| 1360 | "Converts an Absyn.Parallelism to SCode.Parallelism." | ||
| 1361 | input Absyn.Parallelism inParallelism; | ||
| 1362 | output SCode.Parallelism outParallelism; | ||
| 1363 | algorithm | ||
| 1364 | outParallelism := match inParallelism | ||
| 1365 | case Absyn.PARGLOBAL() then SCode.PARGLOBAL(); | ||
| 1366 | case Absyn.PARLOCAL() then SCode.PARLOCAL(); | ||
| 1367 | case Absyn.NON_PARALLEL() then SCode.NON_PARALLEL(); | ||
| 1368 | end match; | ||
| 1369 | end translateParallelism; | ||
| 1370 | |||
| 1371 | protected function translateVariability | ||
| 1372 | "Converts an Absyn.Variability to SCode.Variability." | ||
| 1373 | input Absyn.Variability inVariability; | ||
| 1374 | output SCode.Variability outVariability; | ||
| 1375 | algorithm | ||
| 1376 | outVariability := match inVariability | ||
| 1377 | case Absyn.VAR() then SCode.VAR(); | ||
| 1378 | case Absyn.DISCRETE() then SCode.DISCRETE(); | ||
| 1379 | case Absyn.PARAM() then SCode.PARAM(); | ||
| 1380 | case Absyn.CONST() then SCode.CONST(); | ||
| 1381 | end match; | ||
| 1382 | end translateVariability; | ||
| 1383 | |||
| 1384 | protected function translateEquations | ||
| 1385 | "This function transforms a list of Absyn.Equation to a list of | ||
| 1386 | SCode.Equation, by applying the translateEquation function to each | ||
| 1387 | equation." | ||
| 1388 | input list<Absyn.EquationItem> inAbsynEquationItemLst; | ||
| 1389 | input Boolean inIsInitial; | ||
| 1390 | output list<SCode.Equation> outEquationLst; | ||
| 1391 | algorithm | ||
| 1392 |
2/2✓ Branch 0 taken 10009695 times.
✓ Branch 1 taken 2022924 times.
|
12032619 | outEquationLst := list( |
| 1393 | match eq | ||
| 1394 | local | ||
| 1395 | SCode.Comment com; | ||
| 1396 | SourceInfo info; | ||
| 1397 | case Absyn.EQUATIONITEM() | ||
| 1398 | algorithm | ||
| 1399 | 9412008 | (com,info) := translateCommentWithLineInfoChanges(eq.comment, eq.info); | |
| 1400 | 9412008 | then translateEquation(eq.equation_,com,info,inIsInitial); | |
| 1401 | end match | ||
| 1402 | for eq guard match eq case Absyn.EQUATIONITEM() then true; else false; end match in inAbsynEquationItemLst | ||
| 1403 | ); | ||
| 1404 | end translateEquations; | ||
| 1405 | |||
| 1406 | protected function translateCommentWithLineInfoChanges | ||
| 1407 | "turns an Absyn.Comment into an SCode.Comment" | ||
| 1408 | input Option<Absyn.Comment> inComment; | ||
| 1409 | input SourceInfo inInfo; | ||
| 1410 | output SCode.Comment outComment; | ||
| 1411 | output SourceInfo outInfo; | ||
| 1412 | algorithm | ||
| 1413 | 45578733 | outComment := translateComment(inComment); | |
| 1414 | 45578733 | outInfo := getInfoAnnotationOrDefault(outComment, inInfo); | |
| 1415 | end translateCommentWithLineInfoChanges; | ||
| 1416 | |||
| 1417 | protected function getInfoAnnotationOrDefault "Replaces the file info if there is an annotation __OpenModelica_FileInfo=(\"fileName\",line). Should be improved." | ||
| 1418 | input SCode.Comment comment; | ||
| 1419 | input SourceInfo default; | ||
| 1420 | output SourceInfo info; | ||
| 1421 | algorithm | ||
| 1422 | info := match comment | ||
| 1423 | local | ||
| 1424 | list<SCode.SubMod> lst; | ||
| 1425 | case SCode.COMMENT(annotation_=SOME(SCode.ANNOTATION(modification=SCode.MOD(subModLst=lst)))) | ||
| 1426 | 11560847 | then getInfoAnnotationOrDefault2(lst,default); | |
| 1427 | else default; | ||
| 1428 | end match; | ||
| 1429 | end getInfoAnnotationOrDefault; | ||
| 1430 | |||
| 1431 | protected function getInfoAnnotationOrDefault2 | ||
| 1432 | input list<SCode.SubMod> lst; | ||
| 1433 | input SourceInfo default; | ||
| 1434 | output SourceInfo info; | ||
| 1435 | algorithm | ||
| 1436 | info := match lst | ||
| 1437 | local | ||
| 1438 | list<SCode.SubMod> rest; | ||
| 1439 | String fileName; | ||
| 1440 | Integer line; | ||
| 1441 | case {} then default; | ||
| 1442 | case SCode.NAMEMOD(ident="__OpenModelica_FileInfo",mod=SCode.MOD(binding=SOME(Absyn.TUPLE({Absyn.STRING(fileName),Absyn.INTEGER(line)}))))::_ | ||
| 1443 | ✗ | then SOURCEINFO(fileName,false,line,0,line,0,0.0); | |
| 1444 | 11910990 | case _::rest then getInfoAnnotationOrDefault2(rest,default); | |
| 1445 | end match; | ||
| 1446 | end getInfoAnnotationOrDefault2; | ||
| 1447 | |||
| 1448 | protected function translateComment | ||
| 1449 | "turns an Absyn.Comment into an SCode.Comment" | ||
| 1450 | input Option<Absyn.Comment> inComment; | ||
| 1451 | output SCode.Comment outComment; | ||
| 1452 | algorithm | ||
| 1453 | outComment := match inComment | ||
| 1454 | local | ||
| 1455 | Option<Absyn.Annotation> absann; | ||
| 1456 | Option<SCode.Annotation> ann; | ||
| 1457 | Option<String> ostr; | ||
| 1458 | |||
| 1459 | case NONE() then SCode.noComment; | ||
| 1460 | case SOME(Absyn.COMMENT(absann,ostr)) | ||
| 1461 | algorithm | ||
| 1462 | 23023508 | ann := translateAnnotationOpt(absann); | |
| 1463 | 23023508 | ostr := Util.applyOption(ostr,System.unescapedString); | |
| 1464 | 23023508 | then SCode.COMMENT(ann,ostr); | |
| 1465 | end match; | ||
| 1466 | end translateComment; | ||
| 1467 | |||
| 1468 | protected function translateCommentList | ||
| 1469 | "turns an Absyn.Comment into an SCode.Comment" | ||
| 1470 | input list<Absyn.Annotation> inAnns; | ||
| 1471 | input Option<String> inString; | ||
| 1472 | output SCode.Comment outComment; | ||
| 1473 | algorithm | ||
| 1474 | outComment := match inAnns | ||
| 1475 | local | ||
| 1476 | Absyn.Annotation absann; | ||
| 1477 | list<Absyn.Annotation> anns; | ||
| 1478 | Option<SCode.Annotation> ann; | ||
| 1479 | Option<String> ostr; | ||
| 1480 | |||
| 1481 | 1154136 | case {} then SCode.COMMENT(NONE(),inString); | |
| 1482 | case {absann} | ||
| 1483 | algorithm | ||
| 1484 | 5737435 | ann := translateAnnotation(absann); | |
| 1485 | 5737435 | ostr := Util.applyOption(inString,System.unescapedString); | |
| 1486 | 5737435 | then SCode.COMMENT(ann,ostr); | |
| 1487 | case absann::anns | ||
| 1488 | algorithm | ||
| 1489 | 46 | absann := AbsynUtil.mergeAnnotationsList(absann, anns); | |
| 1490 | 46 | ann := translateAnnotation(absann); | |
| 1491 | 46 | ostr := Util.applyOption(inString,System.unescapedString); | |
| 1492 | 46 | then SCode.COMMENT(ann,ostr); | |
| 1493 | end match; | ||
| 1494 | end translateCommentList; | ||
| 1495 | |||
| 1496 | protected function translateCommentSeparate | ||
| 1497 | "turns an Absyn.Comment into an SCode.Annotation + string" | ||
| 1498 | input Option<Absyn.Comment> inComment; | ||
| 1499 | output Option<SCode.Annotation> outAnn; | ||
| 1500 | output Option<String> outStr; | ||
| 1501 | algorithm | ||
| 1502 | (outAnn,outStr) := match inComment | ||
| 1503 | local Absyn.Annotation absann; | ||
| 1504 | Option<SCode.Annotation> ann; | ||
| 1505 | String str; | ||
| 1506 | |||
| 1507 | case NONE() then (NONE(),NONE()); | ||
| 1508 | case SOME(Absyn.COMMENT(NONE(),NONE())) then (NONE(),NONE()); | ||
| 1509 | case SOME(Absyn.COMMENT(NONE(),SOME(str))) then (NONE(),SOME(str)); | ||
| 1510 | case SOME(Absyn.COMMENT(SOME(absann),NONE())) | ||
| 1511 | algorithm | ||
| 1512 | ✗ | ann := translateAnnotation(absann); | |
| 1513 | then | ||
| 1514 | (ann,NONE()); | ||
| 1515 | case SOME(Absyn.COMMENT(SOME(absann),SOME(str))) | ||
| 1516 | algorithm | ||
| 1517 | ✗ | ann := translateAnnotation(absann); | |
| 1518 | then | ||
| 1519 | (ann,SOME(str)); | ||
| 1520 | end match; | ||
| 1521 | end translateCommentSeparate; | ||
| 1522 | |||
| 1523 | protected function translateEquation | ||
| 1524 | input Absyn.Equation inEquation; | ||
| 1525 | input SCode.Comment inComment; | ||
| 1526 | input SourceInfo inInfo; | ||
| 1527 | input Boolean inIsInitial; | ||
| 1528 | output SCode.Equation outEquation; | ||
| 1529 | algorithm | ||
| 1530 | outEquation := match inEquation | ||
| 1531 | local | ||
| 1532 | Absyn.Exp e1, e2, e3; | ||
| 1533 | list<SCode.Equation> else_branch, body; | ||
| 1534 | list<tuple<Absyn.Exp, list<SCode.Equation>>> branches; | ||
| 1535 | String iter_name; | ||
| 1536 | Option<Absyn.Exp> iter_range; | ||
| 1537 | list<Absyn.Exp> conditions; | ||
| 1538 | list<list<SCode.Equation>> bodies; | ||
| 1539 | |||
| 1540 | case Absyn.EQ_IF() | ||
| 1541 | algorithm | ||
| 1542 | 313632 | body := translateEquations(inEquation.equationTrueItems, inIsInitial); | |
| 1543 |
2/2✓ Branch 0 taken 255340 times.
✓ Branch 1 taken 58292 times.
|
568972 | (conditions, bodies) := |
| 1544 | List.map1_2(inEquation.elseIfBranches, translateEqBranch, inIsInitial); | ||
| 1545 | 313632 | conditions := inEquation.ifExp :: conditions; | |
| 1546 | 313632 | else_branch := translateEquations(inEquation.equationElseItems, inIsInitial); | |
| 1547 | 313632 | then | |
| 1548 | SCode.EQ_IF(conditions, body :: bodies, else_branch, inComment, inInfo); | ||
| 1549 | |||
| 1550 | case Absyn.EQ_WHEN_E() | ||
| 1551 | algorithm | ||
| 1552 | 40578 | body := translateEquations(inEquation.whenEquations, inIsInitial); | |
| 1553 |
1/2✓ Branch 0 taken 40578 times.
✗ Branch 1 not taken.
|
81156 | (conditions, bodies) := |
| 1554 | List.map1_2(inEquation.elseWhenEquations, translateEqBranch, inIsInitial); | ||
| 1555 |
7/8✓ Branch 0 taken 2140 times.
✓ Branch 1 taken 40578 times.
✓ Branch 2 taken 2140 times.
✓ Branch 3 taken 40578 times.
✓ Branch 4 taken 2140 times.
✓ Branch 5 taken 40578 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 40578 times.
|
42718 | branches := list((c, b) threaded for c in conditions, b in bodies); |
| 1556 | 40578 | then | |
| 1557 | SCode.EQ_WHEN(inEquation.whenExp, body, branches, inComment, inInfo); | ||
| 1558 | |||
| 1559 | case Absyn.EQ_EQUALS() | ||
| 1560 | 3215301 | then SCode.EQ_EQUALS(inEquation.leftSide, inEquation.rightSide, inComment, inInfo); | |
| 1561 | |||
| 1562 | case Absyn.EQ_PDE() | ||
| 1563 | 4 | then SCode.EQ_PDE(inEquation.leftSide, inEquation.rightSide, inEquation.domain, inComment, inInfo); | |
| 1564 | |||
| 1565 | case Absyn.EQ_CONNECT() | ||
| 1566 | 5555396 | then SCode.EQ_CONNECT(inEquation.connector1, inEquation.connector2, inComment, inInfo); | |
| 1567 | |||
| 1568 | case Absyn.EQ_FOR() | ||
| 1569 | algorithm | ||
| 1570 | 99923 | body := translateEquations(inEquation.forEquations, inIsInitial); | |
| 1571 | |||
| 1572 | // Convert for-loops with multiple iterators into nested for-loops. | ||
| 1573 |
2/2✓ Branch 1 taken 99928 times.
✓ Branch 2 taken 99923 times.
|
199851 | for i in listReverse(inEquation.iterators) loop |
| 1574 | 99928 | (iter_name, iter_range) := translateIterator(i, inInfo); | |
| 1575 | 99928 | body := {SCode.EQ_FOR(iter_name, iter_range, body, inComment, inInfo)}; | |
| 1576 | end for; | ||
| 1577 | 99923 | then | |
| 1578 | listHead(body); | ||
| 1579 | |||
| 1580 | // assert(condition, message) | ||
| 1581 | case Absyn.EQ_NORETCALL(functionName = Absyn.CREF_IDENT(name = "assert"), | ||
| 1582 | functionArgs = Absyn.FUNCTIONARGS(args = {e1, e2}, argNames = {})) | ||
| 1583 | 131895 | then SCode.EQ_ASSERT(e1, e2, ASSERTION_LEVEL_ERROR, inComment, inInfo); | |
| 1584 | |||
| 1585 | // assert(condition, message, level) | ||
| 1586 | case Absyn.EQ_NORETCALL(functionName = Absyn.CREF_IDENT(name = "assert"), | ||
| 1587 | functionArgs = Absyn.FUNCTIONARGS(args = {e1, e2, e3}, argNames = {})) | ||
| 1588 | 505 | then SCode.EQ_ASSERT(e1, e2, e3, inComment, inInfo); | |
| 1589 | |||
| 1590 | // assert(condition, message, level = arg) | ||
| 1591 | case Absyn.EQ_NORETCALL(functionName = Absyn.CREF_IDENT(name = "assert"), | ||
| 1592 | functionArgs = Absyn.FUNCTIONARGS(args = {e1, e2}, | ||
| 1593 | argNames = {Absyn.NAMEDARG("level", e3)})) | ||
| 1594 | 6972 | then SCode.EQ_ASSERT(e1, e2, e3, inComment, inInfo); | |
| 1595 | |||
| 1596 | // terminate(message) | ||
| 1597 | case Absyn.EQ_NORETCALL(functionName = Absyn.CREF_IDENT(name = "terminate"), | ||
| 1598 | functionArgs = Absyn.FUNCTIONARGS(args = {e1}, argNames = {})) | ||
| 1599 | 572 | then SCode.EQ_TERMINATE(e1, inComment, inInfo); | |
| 1600 | |||
| 1601 | // reinit(cref, exp) | ||
| 1602 | case Absyn.EQ_NORETCALL(functionName = Absyn.CREF_IDENT(name = "reinit"), | ||
| 1603 | functionArgs = Absyn.FUNCTIONARGS(args = {e1, e2}, | ||
| 1604 | argNames = {})) | ||
| 1605 | 3915 | then SCode.EQ_REINIT(e1, e2, inComment, inInfo); | |
| 1606 | |||
| 1607 | // Other nonreturning calls. assert, terminate and reinit with the wrong | ||
| 1608 | // number of arguments is also turned into a noretcall, since it's | ||
| 1609 | // preferable to handle the error during instantation instead of here. | ||
| 1610 | case Absyn.EQ_NORETCALL() | ||
| 1611 | 43315 | then SCode.EQ_NORETCALL(Absyn.CALL(inEquation.functionName, inEquation.functionArgs, {}), | |
| 1612 | inComment, inInfo); | ||
| 1613 | |||
| 1614 | end match; | ||
| 1615 | end translateEquation; | ||
| 1616 | |||
| 1617 | protected function translateEqBranch | ||
| 1618 | input tuple<Absyn.Exp, list<Absyn.EquationItem>> inBranch; | ||
| 1619 | input Boolean inIsInitial; | ||
| 1620 | output Absyn.Exp outCondition; | ||
| 1621 | output list<SCode.Equation> outBody; | ||
| 1622 | protected | ||
| 1623 | list<Absyn.EquationItem> body; | ||
| 1624 | algorithm | ||
| 1625 | 80191 | (outCondition, body) := inBranch; | |
| 1626 | 80191 | outBody := translateEquations(body, inIsInitial); | |
| 1627 | end translateEqBranch; | ||
| 1628 | |||
| 1629 | protected function translateIterator | ||
| 1630 | input Absyn.ForIterator inIterator; | ||
| 1631 | input SourceInfo inInfo; | ||
| 1632 | output String outName; | ||
| 1633 | output Option<Absyn.Exp> outRange; | ||
| 1634 | protected | ||
| 1635 | Option<Absyn.Exp> guard_exp; | ||
| 1636 | algorithm | ||
| 1637 | 239186 | Absyn.ITERATOR(name = outName, guardExp = guard_exp, range = outRange) := inIterator; | |
| 1638 | |||
| 1639 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 239186 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 239186 times.
|
239186 | if isSome(guard_exp) then |
| 1640 | ✗ | Error.addSourceMessageAndFail(Error.INTERNAL_ERROR, | |
| 1641 | {"For loops with guards not yet implemented"}, inInfo); | ||
| 1642 | end if; | ||
| 1643 | end translateIterator; | ||
| 1644 | |||
| 1645 | protected function translateElementAddinfo | ||
| 1646 | "function: translateElementAddinfo" | ||
| 1647 | input SCode.Element elem; | ||
| 1648 | input SourceInfo nfo; | ||
| 1649 | output SCode.Element oelem; | ||
| 1650 | algorithm | ||
| 1651 | oelem := match elem | ||
| 1652 | local | ||
| 1653 | SCode.Ident a1; | ||
| 1654 | SCode.Attributes a6; | ||
| 1655 | Absyn.TypeSpec a7; | ||
| 1656 | SCode.Mod a8; | ||
| 1657 | SCode.Comment a10; | ||
| 1658 | Option<Absyn.Exp> a11; | ||
| 1659 | SCode.Prefixes p; | ||
| 1660 | |||
| 1661 | case SCode.COMPONENT(a1,p,a6,a7,a8,a10,a11,_) | ||
| 1662 | ✗ | then SCode.COMPONENT(a1,p,a6,a7,a8,a10,a11,nfo); | |
| 1663 | |||
| 1664 | else elem; | ||
| 1665 | end match; | ||
| 1666 | end translateElementAddinfo; | ||
| 1667 | |||
| 1668 | /* Modification management */ | ||
| 1669 | public function translateMod | ||
| 1670 | "Builds an SCode.Mod from an Absyn.Modification." | ||
| 1671 | input Option<Absyn.Modification> inMod; | ||
| 1672 | input SCode.Final finalPrefix; | ||
| 1673 | input SCode.Each eachPrefix; | ||
| 1674 | input Option<String> comment; | ||
| 1675 | input SourceInfo info; | ||
| 1676 | input Boolean keepEmpty = false; // Keep empty modifiers, e.g. (x). | ||
| 1677 | output SCode.Mod outMod; | ||
| 1678 | protected | ||
| 1679 | list<Absyn.ElementArg> args; | ||
| 1680 | Absyn.EqMod eqmod; | ||
| 1681 | list<SCode.SubMod> subs; | ||
| 1682 | Option<Absyn.Exp> binding; | ||
| 1683 | algorithm | ||
| 1684 | (args, eqmod) := match inMod | ||
| 1685 | case SOME(Absyn.CLASSMOD(elementArgLst = args, eqMod = eqmod)) then (args, eqmod); | ||
| 1686 | else ({}, Absyn.NOMOD()); | ||
| 1687 | end match; | ||
| 1688 | |||
| 1689 |
2/2✓ Branch 0 taken 48682848 times.
✓ Branch 1 taken 81908671 times.
|
130591519 | subs := if listEmpty(args) then {} else translateArgs(args, keepEmpty); |
| 1690 | |||
| 1691 | binding := match eqmod | ||
| 1692 | 63162056 | case Absyn.EQMOD() then SOME(eqmod.exp); | |
| 1693 | else NONE(); | ||
| 1694 | end match; | ||
| 1695 | |||
| 1696 | outMod := match (subs, binding, finalPrefix, eachPrefix) | ||
| 1697 | case ({}, NONE(), SCode.NOT_FINAL(), SCode.NOT_EACH()) then SCode.NOMOD(); | ||
| 1698 | 111141359 | else SCode.MOD(finalPrefix, eachPrefix, subs, binding, comment, info); | |
| 1699 | end match; | ||
| 1700 | end translateMod; | ||
| 1701 | |||
| 1702 | protected function translateArgs | ||
| 1703 | input list<Absyn.ElementArg> args; | ||
| 1704 | input Boolean keepEmpty; | ||
| 1705 | output list<SCode.SubMod> subMods = {}; | ||
| 1706 | protected | ||
| 1707 | SCode.Mod smod; | ||
| 1708 | SCode.Element elem; | ||
| 1709 | SCode.SubMod sub; | ||
| 1710 | Absyn.ComponentRef cr1, cr2; | ||
| 1711 | String name; | ||
| 1712 | algorithm | ||
| 1713 |
2/2✓ Branch 0 taken 79521362 times.
✓ Branch 1 taken 48682848 times.
|
128204210 | for arg in args loop |
| 1714 | subMods := match arg | ||
| 1715 | case Absyn.MODIFICATION() | ||
| 1716 | algorithm | ||
| 1717 | 79238730 | smod := translateMod(arg.modification, SCodeUtil.boolFinal(arg.finalPrefix), | |
| 1718 | translateEach(arg.eachPrefix), arg.comment, arg.info); | ||
| 1719 | |||
| 1720 |
4/4✓ Branch 1 taken 116859 times.
✓ Branch 2 taken 79121871 times.
✓ Branch 3 taken 95940 times.
✓ Branch 4 taken 20919 times.
|
79238730 | if not SCodeUtil.isEmptyMod(smod) or keepEmpty then |
| 1721 | 79217811 | sub := translateSub(arg.path, smod, arg.info); | |
| 1722 | subMods := sub :: subMods; | ||
| 1723 | end if; | ||
| 1724 | then | ||
| 1725 | subMods; | ||
| 1726 | |||
| 1727 | case Absyn.REDECLARATION() | ||
| 1728 | algorithm | ||
| 1729 |
2/4✗ Branch 2 not taken.
✓ Branch 3 taken 282614 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 282614 times.
|
282614 | elem::{} := translateElementspec(arg.constrainClass, arg.finalPrefix, |
| 1730 | Absyn.NOT_INNER_OUTER(), SOME(arg.redeclareKeywords), SCode.PUBLIC(), | ||
| 1731 | arg.elementSpec, arg.info); | ||
| 1732 | |||
| 1733 | 282614 | sub := SCode.NAMEMOD(AbsynUtil.elementSpecName(arg.elementSpec), | |
| 1734 | SCode.REDECL( | ||
| 1735 | SCodeUtil.boolFinal(arg.finalPrefix), | ||
| 1736 | translateEach(arg.eachPrefix), | ||
| 1737 | elem)); | ||
| 1738 | then | ||
| 1739 | sub :: subMods; | ||
| 1740 | |||
| 1741 | case Absyn.ELEMENTARGCOMMENT() then subMods; | ||
| 1742 | |||
| 1743 | case Absyn.INHERITANCEBREAK(Absyn.EQ_CONNECT(connector1 = Absyn.ComponentRef.CREF_IDENT(name = "break"), | ||
| 1744 | connector2 = Absyn.ComponentRef.CREF_IDENT(name = name))) | ||
| 1745 | 10 | then SCode.SubMod.NAMEMOD(name, SCode.Mod.BREAK_COMPONENT(arg.info)) :: subMods; | |
| 1746 | |||
| 1747 | case Absyn.INHERITANCEBREAK(Absyn.EQ_CONNECT(connector1 = cr1, connector2 = cr2)) | ||
| 1748 | 5 | then SCode.SubMod.NAMEMOD("", SCode.Mod.BREAK_CONNECT(cr1, cr2, arg.info)) :: subMods; | |
| 1749 | |||
| 1750 | end match; | ||
| 1751 | end for; | ||
| 1752 | |||
| 1753 | 48682848 | subMods := listReverse(subMods); | |
| 1754 | end translateArgs; | ||
| 1755 | |||
| 1756 | protected function translateSub | ||
| 1757 | "This function converts a Absyn.ComponentRef plus a list | ||
| 1758 | of modifications into a number of nested SCode.SUBMOD." | ||
| 1759 | input Absyn.Path inPath; | ||
| 1760 | input SCode.Mod inMod; | ||
| 1761 | input SourceInfo info; | ||
| 1762 | output SCode.SubMod outSubMod; | ||
| 1763 | algorithm | ||
| 1764 | outSubMod := match inPath | ||
| 1765 | local | ||
| 1766 | String i; | ||
| 1767 | Absyn.Path path; | ||
| 1768 | SCode.Mod mod; | ||
| 1769 | SCode.SubMod sub; | ||
| 1770 | |||
| 1771 | // Then the normal rules | ||
| 1772 | 79217811 | case Absyn.IDENT(name = i) then SCode.NAMEMOD(i,inMod); | |
| 1773 | case Absyn.QUALIFIED(name = i,path = path) | ||
| 1774 | algorithm | ||
| 1775 | 52 | sub := translateSub(path, inMod, info); | |
| 1776 | 52 | mod := SCode.MOD(SCode.NOT_FINAL(),SCode.NOT_EACH(),{sub},NONE(),NONE(),info); | |
| 1777 | 52 | then SCode.NAMEMOD(i,mod); | |
| 1778 | end match; | ||
| 1779 | end translateSub; | ||
| 1780 | |||
| 1781 | protected function makeTypeVarElement | ||
| 1782 | input String str; | ||
| 1783 | input SourceInfo info; | ||
| 1784 | output SCode.Element elt; | ||
| 1785 | protected | ||
| 1786 | SCode.ClassDef cd; | ||
| 1787 | Absyn.TypeSpec ts; | ||
| 1788 | algorithm | ||
| 1789 | ts := Absyn.TCOMPLEX(Absyn.IDENT("polymorphic"),{Absyn.TPATH(Absyn.IDENT("Any"),NONE())},NONE()); | ||
| 1790 | 163856 | cd := SCode.DERIVED(ts,SCode.NOMOD(), | |
| 1791 | SCode.ATTR({},SCode.POTENTIAL(), SCode.NON_PARALLEL(), SCode.VAR(),Absyn.BIDIR(),Absyn.NONFIELD())); | ||
| 1792 | 163856 | elt := SCode.CLASS( | |
| 1793 | str, | ||
| 1794 | SCode.PREFIXES( | ||
| 1795 | SCode.PUBLIC(), | ||
| 1796 | SCode.NOT_REDECLARE(), | ||
| 1797 | SCode.FINAL(), | ||
| 1798 | Absyn.NOT_INNER_OUTER(), | ||
| 1799 | SCode.NOT_REPLACEABLE()), | ||
| 1800 | SCode.NOT_ENCAPSULATED(),SCode.NOT_PARTIAL(),SCode.R_TYPE(),cd,SCode.noComment,info); | ||
| 1801 | end makeTypeVarElement; | ||
| 1802 | |||
| 1803 | protected function translateEach | ||
| 1804 | input Absyn.Each inAEach; | ||
| 1805 | output SCode.Each outSEach; | ||
| 1806 | algorithm | ||
| 1807 | outSEach := match inAEach | ||
| 1808 | case Absyn.EACH() then SCode.EACH(); | ||
| 1809 | case Absyn.NON_EACH() then SCode.NOT_EACH(); | ||
| 1810 | end match; | ||
| 1811 | end translateEach; | ||
| 1812 | |||
| 1813 | protected function checkTypeSpec | ||
| 1814 | input Absyn.TypeSpec ts; | ||
| 1815 | input SourceInfo info; | ||
| 1816 | algorithm | ||
| 1817 | () := match ts | ||
| 1818 | local | ||
| 1819 | list<Absyn.TypeSpec> tss; | ||
| 1820 | Absyn.TypeSpec ts2; | ||
| 1821 | String str; | ||
| 1822 | case Absyn.TPATH() then (); | ||
| 1823 | case Absyn.TCOMPLEX(path=Absyn.IDENT("tuple"),typeSpecs={ts2}) | ||
| 1824 | algorithm | ||
| 1825 | ✗ | str := AbsynUtil.typeSpecString(ts); | |
| 1826 | ✗ | Error.addSourceMessage(Error.TCOMPLEX_TUPLE_ONE_NAME,{str},info); | |
| 1827 | ✗ | checkTypeSpec(ts2,info); | |
| 1828 | then (); | ||
| 1829 | // It is okay for tuples to have multiple typespecs | ||
| 1830 | case Absyn.TCOMPLEX(path=Absyn.IDENT("tuple"),typeSpecs=tss as (_::_::_)) | ||
| 1831 | algorithm | ||
| 1832 | 16614 | List.map1_0(tss, checkTypeSpec, info); | |
| 1833 | then (); | ||
| 1834 | case Absyn.TCOMPLEX(typeSpecs={ts2}) | ||
| 1835 | algorithm | ||
| 1836 | 142304 | checkTypeSpec(ts2,info); | |
| 1837 | then (); | ||
| 1838 | case Absyn.TCOMPLEX(typeSpecs=tss) | ||
| 1839 | algorithm | ||
| 1840 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 857 times.
|
857 | if listMember(ts.path, {Absyn.IDENT("list"),Absyn.IDENT("List"),Absyn.IDENT("array"),Absyn.IDENT("Array"),Absyn.IDENT("polymorphic"),Absyn.IDENT("Option")}) then |
| 1841 | ✗ | str := AbsynUtil.typeSpecString(ts); | |
| 1842 | ✗ | Error.addSourceMessage(Error.TCOMPLEX_MULTIPLE_NAMES,{str},info); | |
| 1843 | ✗ | List.map1_0(tss, checkTypeSpec, info); | |
| 1844 | end if; | ||
| 1845 | then (); | ||
| 1846 | end match; | ||
| 1847 | end checkTypeSpec; | ||
| 1848 | |||
| 1849 | annotation(__OpenModelica_Interface="frontend_dump"); | ||
| 1850 | end AbsynToSCode; | ||
| 1851 |