OMCompiler/Compiler/NFFrontEnd/NFFlatModel.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 uniontype NFFlatModel | ||
| 37 | import Equation = NFEquation; | ||
| 38 | import Algorithm = NFAlgorithm; | ||
| 39 | import Variable = NFVariable; | ||
| 40 | import BaseModelica; | ||
| 41 | |||
| 42 | protected | ||
| 43 | import Absyn; | ||
| 44 | import Binding = NFBinding; | ||
| 45 | import Call = NFCall; | ||
| 46 | import Class = NFClass; | ||
| 47 | import ComplexType = NFComplexType; | ||
| 48 | import Component = NFComponent; | ||
| 49 | import DAE; | ||
| 50 | import DAE.ElementSource; | ||
| 51 | import Dimension = NFDimension; | ||
| 52 | import ErrorExt; | ||
| 53 | import ExpandExp = NFExpandExp; | ||
| 54 | import Expression = NFExpression; | ||
| 55 | import FlatModelicaUtil = NFFlatModelicaUtil; | ||
| 56 | import Flatten = NFFlatten; | ||
| 57 | import NFFlatten.FunctionTree; | ||
| 58 | import FunctionInverse = NFFunctionInverse; | ||
| 59 | import Inline = NFInline; | ||
| 60 | import InstContext = NFInstContext; | ||
| 61 | import IOStream; | ||
| 62 | import Lookup = NFLookup; | ||
| 63 | import MetaModelica.Dangerous.listReverseInPlace; | ||
| 64 | import NFClassTree.ClassTree; | ||
| 65 | import NFComponentRef.ComponentRef; | ||
| 66 | import NFFunction.Function; | ||
| 67 | import NFInstNode.InstNode; | ||
| 68 | import NFPrefixes.Visibility; | ||
| 69 | import NFSubscript.Subscript; | ||
| 70 | import Prefixes = NFPrefixes; | ||
| 71 | import Scalarize = NFScalarize; | ||
| 72 | import SCode; | ||
| 73 | import Statement = NFStatement; | ||
| 74 | import StringUtil; | ||
| 75 | import Type = NFType; | ||
| 76 | import Typing = NFTyping; | ||
| 77 | import UnorderedMap; | ||
| 78 | import Util; | ||
| 79 | |||
| 80 | import FlatModel = NFFlatModel; | ||
| 81 | |||
| 82 | type TypeMap = UnorderedMap<Absyn.Path, Type>; | ||
| 83 | |||
| 84 | public | ||
| 85 | record FLAT_MODEL | ||
| 86 | Absyn.Path name; | ||
| 87 | list<Variable> variables; | ||
| 88 | list<Equation> equations; | ||
| 89 | list<Equation> initialEquations; | ||
| 90 | list<Algorithm> algorithms; | ||
| 91 | list<Algorithm> initialAlgorithms; | ||
| 92 | ElementSource source; | ||
| 93 | end FLAT_MODEL; | ||
| 94 | |||
| 95 | function mapExp | ||
| 96 | input output FlatModel flatModel; | ||
| 97 | input MapFn fn; | ||
| 98 | |||
| 99 | partial function MapFn | ||
| 100 | input output Expression exp; | ||
| 101 | end MapFn; | ||
| 102 | algorithm | ||
| 103 |
4/4✓ Branch 0 taken 378396 times.
✓ Branch 1 taken 1453 times.
✓ Branch 2 taken 378396 times.
✓ Branch 3 taken 1453 times.
|
379849 | flatModel.variables := list(Variable.mapExpShallow(v, fn) for v in flatModel.variables); |
| 104 | flatModel.equations := Equation.mapExpList(flatModel.equations, fn); | ||
| 105 | flatModel.initialEquations := Equation.mapExpList(flatModel.initialEquations, fn); | ||
| 106 | flatModel.algorithms := Algorithm.mapExpList(flatModel.algorithms, fn); | ||
| 107 | flatModel.initialAlgorithms := Algorithm.mapExpList(flatModel.initialAlgorithms, fn); | ||
| 108 | end mapExp; | ||
| 109 | |||
| 110 | function mapEquations | ||
| 111 | input output FlatModel flatModel; | ||
| 112 | input MapFn fn; | ||
| 113 | |||
| 114 | partial function MapFn | ||
| 115 | input output Equation eq; | ||
| 116 | end MapFn; | ||
| 117 | algorithm | ||
| 118 |
8/8✓ Branch 0 taken 152998 times.
✓ Branch 1 taken 1218 times.
✓ Branch 2 taken 152998 times.
✓ Branch 3 taken 1218 times.
✓ Branch 5 taken 2253 times.
✓ Branch 6 taken 1218 times.
✓ Branch 7 taken 2253 times.
✓ Branch 8 taken 1218 times.
|
156469 | flatModel.equations := list(Equation.map(eq, fn) for eq in flatModel.equations); |
| 119 | flatModel.initialEquations := list(Equation.map(eq, fn) for eq in flatModel.initialEquations); | ||
| 120 | end mapEquations; | ||
| 121 | |||
| 122 | function mapAlgorithms | ||
| 123 | input output FlatModel flatModel; | ||
| 124 | input MapFn fn; | ||
| 125 | |||
| 126 | partial function MapFn | ||
| 127 | input output Algorithm alg; | ||
| 128 | end MapFn; | ||
| 129 | algorithm | ||
| 130 |
10/12✓ Branch 0 taken 132 times.
✓ Branch 1 taken 1218 times.
✓ Branch 2 taken 132 times.
✓ Branch 3 taken 1218 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 132 times.
✓ Branch 8 taken 46 times.
✓ Branch 9 taken 1218 times.
✓ Branch 10 taken 46 times.
✓ Branch 11 taken 1218 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 46 times.
|
1396 | flatModel.algorithms := list(fn(alg) for alg in flatModel.algorithms); |
| 131 | flatModel.initialAlgorithms := list(fn(alg) for alg in flatModel.initialAlgorithms); | ||
| 132 | end mapAlgorithms; | ||
| 133 | |||
| 134 | function fullName | ||
| 135 | input FlatModel flatModel; | ||
| 136 | output String name = AbsynUtil.pathString(flatModel.name); | ||
| 137 | end fullName; | ||
| 138 | |||
| 139 | function className | ||
| 140 | input FlatModel flatModel; | ||
| 141 | output String name = AbsynUtil.pathLastIdent(flatModel.name); | ||
| 142 | end className; | ||
| 143 | |||
| 144 | function toString | ||
| 145 | input FlatModel flatModel; | ||
| 146 | input FunctionTree functions; | ||
| 147 | input Boolean printBindingTypes = false; | ||
| 148 | output String str = IOStream.string(toStream(flatModel, functions, printBindingTypes)); | ||
| 149 | end toString; | ||
| 150 | |||
| 151 | function printString | ||
| 152 | input FlatModel flatModel; | ||
| 153 | input FunctionTree functions; | ||
| 154 | input Boolean printBindingTypes = false; | ||
| 155 | protected | ||
| 156 | IOStream.IOStream s; | ||
| 157 | algorithm | ||
| 158 | 6 | s := toStream(flatModel, functions, printBindingTypes); | |
| 159 | 6 | IOStream.print(s, IOStream.stdOutput); | |
| 160 | end printString; | ||
| 161 | |||
| 162 | function toStream | ||
| 163 | input FlatModel flatModel; | ||
| 164 | input FunctionTree functions; | ||
| 165 | input Boolean printBindingTypes = false; | ||
| 166 | output IOStream.IOStream s; | ||
| 167 | algorithm | ||
| 168 | 6 | s := IOStream.create(getInstanceName(), IOStream.IOStreamType.LIST()); | |
| 169 | 6 | s := appendStream(flatModel, functions, printBindingTypes, s); | |
| 170 | end toStream; | ||
| 171 | |||
| 172 | function appendStream | ||
| 173 | input FlatModel flatModel; | ||
| 174 | input FunctionTree functions; | ||
| 175 | input Boolean printBindingTypes = false; | ||
| 176 | input output IOStream.IOStream s; | ||
| 177 | protected | ||
| 178 | String name = className(flatModel); | ||
| 179 | algorithm | ||
| 180 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
6 | for fn in FunctionTree.listValues(functions) loop |
| 181 | ✗ | s := Function.toStream(fn, "", s); | |
| 182 | ✗ | s := IOStream.append(s, ";\n\n"); | |
| 183 | end for; | ||
| 184 | |||
| 185 | 6 | s := IOStream.append(s, "class " + name + "\n"); | |
| 186 | |||
| 187 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 6 times.
|
38 | for v in flatModel.variables loop |
| 188 | 32 | s := Variable.toStream(v, " ", printBindingTypes, s); | |
| 189 | 32 | s := IOStream.append(s, ";\n"); | |
| 190 | end for; | ||
| 191 | |||
| 192 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if not listEmpty(flatModel.initialEquations) then |
| 193 | ✗ | s := IOStream.append(s, "initial equation\n"); | |
| 194 | ✗ | s := Equation.toStreamList(flatModel.initialEquations, " ", s); | |
| 195 | end if; | ||
| 196 | |||
| 197 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if not listEmpty(flatModel.equations) then |
| 198 | 6 | s := IOStream.append(s, "equation\n"); | |
| 199 | 6 | s := Equation.toStreamList(flatModel.equations, " ", s); | |
| 200 | end if; | ||
| 201 | |||
| 202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | for alg in flatModel.initialAlgorithms loop |
| 203 | ✗ | if not listEmpty(alg.statements) then | |
| 204 | ✗ | s := IOStream.append(s, "initial algorithm\n"); | |
| 205 | ✗ | s := Statement.toStreamList(alg.statements, " ", s); | |
| 206 | end if; | ||
| 207 | end for; | ||
| 208 | |||
| 209 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
12 | for alg in flatModel.algorithms loop |
| 210 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if not listEmpty(alg.statements) then |
| 211 | 6 | s := IOStream.append(s, "algorithm\n"); | |
| 212 | 6 | s := Statement.toStreamList(alg.statements, " ", s); | |
| 213 | end if; | ||
| 214 | end for; | ||
| 215 | |||
| 216 | 6 | s := IOStream.append(s, "end " + name + ";\n"); | |
| 217 | end appendStream; | ||
| 218 | |||
| 219 | function toFlatString | ||
| 220 | "Returns a string containing the flat Modelica representation of the given model." | ||
| 221 | input FlatModel flatModel; | ||
| 222 | input FunctionTree functions; | ||
| 223 | input Boolean printBindingTypes = false; | ||
| 224 | output String str = IOStream.string(toFlatStream(flatModel, functions, printBindingTypes)); | ||
| 225 | end toFlatString; | ||
| 226 | |||
| 227 | function printFlatString | ||
| 228 | "Prints a flat Modelica representation of the given model to standard output." | ||
| 229 | input FlatModel flatModel; | ||
| 230 | input FunctionTree functions; | ||
| 231 | input Boolean printBindingTypes = false; | ||
| 232 | protected | ||
| 233 | IOStream.IOStream s; | ||
| 234 | algorithm | ||
| 235 | ✗ | s := toFlatStream(flatModel, functions, printBindingTypes); | |
| 236 | ✗ | IOStream.print(s, IOStream.stdOutput); | |
| 237 | end printFlatString; | ||
| 238 | |||
| 239 | function toFlatStream | ||
| 240 | "Returns a new IOStream containing the flat Modelica representation of the given model." | ||
| 241 | input FlatModel flatModel; | ||
| 242 | input FunctionTree functions; | ||
| 243 | input Boolean printBindingTypes = false; | ||
| 244 | output IOStream.IOStream s; | ||
| 245 | algorithm | ||
| 246 | 32 | s := IOStream.create(className(flatModel), IOStream.IOStreamType.LIST()); | |
| 247 | 32 | s := appendFlatStream(flatModel, functions, printBindingTypes, s); | |
| 248 | end toFlatStream; | ||
| 249 | |||
| 250 | function appendFlatStream | ||
| 251 | "Appends the flat Modelica representation of the given model to an existing IOStream." | ||
| 252 | input FlatModel flatModel; | ||
| 253 | input FunctionTree functions; | ||
| 254 | input Boolean printBindingTypes = false; | ||
| 255 | input output IOStream.IOStream s; | ||
| 256 | protected | ||
| 257 | FlatModel flat_model = flatModel; | ||
| 258 | String name = Util.makeQuotedIdentifier(className(flatModel)); | ||
| 259 | BaseModelica.OutputFormat format; | ||
| 260 | Boolean scalarize; | ||
| 261 | list<Function> funcs = FunctionTree.listValues(functions); | ||
| 262 | algorithm | ||
| 263 | 32 | format := BaseModelica.formatFromFlags(); | |
| 264 | 32 | scalarize := Flags.isConfigFlagSet(Flags.BASE_MODELICA_OPTIONS, "scalarize"); | |
| 265 | |||
| 266 |
2/8✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 32 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
32 | if Flags.getConfigString(Flags.OBFUSCATE) == "protected" or |
| 267 | Flags.getConfigString(Flags.OBFUSCATE) == "encrypted" then | ||
| 268 | ✗ | flat_model := obfuscate(flat_model); | |
| 269 | end if; | ||
| 270 | |||
| 271 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 29 times.
|
32 | if BaseModelica.inlineFunctions() then |
| 272 | 3 | (flat_model, funcs) := inlineFunctions(flat_model); | |
| 273 | end if; | ||
| 274 | |||
| 275 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 27 times.
|
32 | if scalarize then |
| 276 | 5 | flat_model.variables := Scalarize.scalarizeVariables(flat_model.variables, forceScalarize = true); | |
| 277 | flat_model.equations := Equation.splitRecordEquations(flat_model.equations); | ||
| 278 | 5 | flat_model.equations := Scalarize.scalarizeEquations(flat_model.equations, forceScalarize = true); | |
| 279 | flat_model.initialEquations := Equation.splitRecordEquations(flat_model.initialEquations); | ||
| 280 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 5 times.
|
5 | flat_model.initialEquations := Scalarize.scalarizeEquations(flat_model.initialEquations, forceScalarize = true); |
| 281 | flat_model.algorithms := list(Flatten.unrollForStatementsInAlg(a) for a in flat_model.algorithms); | ||
| 282 | flat_model.initialAlgorithms := list(Flatten.unrollForStatementsInAlg(a) for a in flat_model.initialAlgorithms); | ||
| 283 | 5 | flat_model := mapExp(flat_model, ExpandExp.expandCallArgs); | |
| 284 | else | ||
| 285 | 27 | flat_model.variables := reconstructRecordInstances(flat_model.variables); | |
| 286 | 27 | flat_model.variables := List.filterOnFalse(flat_model.variables, Variable.isEmptyArray); | |
| 287 | end if; | ||
| 288 | |||
| 289 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | if format.moveBindings then |
| 290 | ✗ | flat_model := moveBindings(flat_model); | |
| 291 | end if; | ||
| 292 | |||
| 293 | 32 | s := IOStream.append(s, "//! base 0.1.0\n"); | |
| 294 | 32 | s := IOStream.append(s, "package " + name + "\n"); | |
| 295 | |||
| 296 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 32 times.
|
60 | for fn in funcs loop |
| 297 |
3/4✓ Branch 1 taken 10 times.
✓ Branch 2 taken 18 times.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
28 | if not (Function.isDefaultRecordConstructor(fn) or Function.isExternalObjectConstructorOrDestructor(fn)) then |
| 298 | // Function parameters are not affected by the scalarization mode, so use default format here. | ||
| 299 | 10 | s := Function.toFlatStream(fn, BaseModelica.defaultFormat, " ", s); | |
| 300 | 10 | s := IOStream.append(s, ";\n\n"); | |
| 301 | end if; | ||
| 302 | end for; | ||
| 303 | |||
| 304 |
2/2✓ Branch 1 taken 28 times.
✓ Branch 2 taken 32 times.
|
60 | for ty in collectFlatTypes(flat_model, funcs) loop |
| 305 | 28 | s := Type.toFlatDeclarationStream(ty, format, " ", s); | |
| 306 | 28 | s := IOStream.append(s, ";\n\n"); | |
| 307 | end for; | ||
| 308 | |||
| 309 | 32 | s := IOStream.append(s, " model " + name); | |
| 310 | 32 | s := FlatModelicaUtil.appendElementSourceCommentString(flat_model.source, s); | |
| 311 | 32 | s := IOStream.append(s, "\n"); | |
| 312 | |||
| 313 |
2/2✓ Branch 0 taken 847 times.
✓ Branch 1 taken 32 times.
|
879 | for v in flat_model.variables loop |
| 314 | 847 | s := Variable.toFlatStream(v, format, " ", printBindingTypes, s); | |
| 315 | 847 | s := IOStream.append(s, ";\n"); | |
| 316 | end for; | ||
| 317 | |||
| 318 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | if not listEmpty(flat_model.initialEquations) then |
| 319 | ✗ | s := IOStream.append(s, " initial equation\n"); | |
| 320 | ✗ | s := Equation.toFlatStreamList(flat_model.initialEquations, format, " ", s); | |
| 321 | end if; | ||
| 322 | |||
| 323 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
|
32 | if not listEmpty(flat_model.equations) then |
| 324 | 24 | s := IOStream.append(s, " equation\n"); | |
| 325 | 24 | s := Equation.toFlatStreamList(flat_model.equations, format, " ", s); | |
| 326 | end if; | ||
| 327 | |||
| 328 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | for alg in flat_model.initialAlgorithms loop |
| 329 | ✗ | if not listEmpty(alg.statements) then | |
| 330 | ✗ | s := IOStream.append(s, " initial algorithm\n"); | |
| 331 | ✗ | s := Statement.toFlatStreamList(alg.statements, format, " ", s); | |
| 332 | end if; | ||
| 333 | end for; | ||
| 334 | |||
| 335 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | for alg in flat_model.algorithms loop |
| 336 | ✗ | if not listEmpty(alg.statements) then | |
| 337 | ✗ | s := IOStream.append(s, " algorithm\n"); | |
| 338 | ✗ | s := Statement.toFlatStreamList(alg.statements, format, " ", s); | |
| 339 | end if; | ||
| 340 | end for; | ||
| 341 | |||
| 342 | 32 | s := FlatModelicaUtil.appendElementSourceCommentAnnotation(flat_model.source, | |
| 343 | NFFlatModelicaUtil.ElementType.ROOT_CLASS, " ", ";\n", s); | ||
| 344 | 32 | s := IOStream.append(s, " end " + name + ";\n"); | |
| 345 | 32 | s := IOStream.append(s, "end " + name + ";\n"); | |
| 346 | end appendFlatStream; | ||
| 347 | |||
| 348 | function inlineFunctions | ||
| 349 | "Tries to inline all function calls in the flat model, and returns the new | ||
| 350 | flat model and a list of functions that couldn't be inlined." | ||
| 351 | input output FlatModel flatModel; | ||
| 352 | output list<Function> remainingFuncs; | ||
| 353 | protected | ||
| 354 | UnorderedSet<Function> funcs; | ||
| 355 | algorithm | ||
| 356 | 3 | funcs := UnorderedSet.new(Function.nameHash, Function.nameEqual); | |
| 357 | 3 | flatModel := mapExp(flatModel, function Expression.map(func = function inlineFunctions_traverser(funcs = funcs))); | |
| 358 | 3 | remainingFuncs := UnorderedSet.toList(funcs); | |
| 359 | end inlineFunctions; | ||
| 360 | |||
| 361 | function inlineFunctions_traverser | ||
| 362 | input Expression exp; | ||
| 363 | input UnorderedSet<Function> funcs; | ||
| 364 | output Expression outExp; | ||
| 365 | protected | ||
| 366 | Function fn; | ||
| 367 | algorithm | ||
| 368 | outExp := match exp | ||
| 369 | case Expression.CALL() | ||
| 370 | algorithm | ||
| 371 | 3 | fn := Call.typedFunction(exp.call); | |
| 372 | |||
| 373 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if Function.isBuiltin(fn) then |
| 374 | outExp := exp; | ||
| 375 | else | ||
| 376 | 3 | outExp := Inline.inlineCallExp(exp, forceInline = true); | |
| 377 | |||
| 378 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
|
3 | if referenceEq(exp, outExp) then |
| 379 | // If the call wasn't inlined, add it to the set of remaining functions. | ||
| 380 | 1 | collectFunction(fn, funcs); | |
| 381 | else | ||
| 382 | // Otherwise, collect any calls in the new expression that couldn't be inlined. | ||
| 383 | 2 | Expression.apply(outExp, function collectFunctions(funcs = funcs)); | |
| 384 | end if; | ||
| 385 | end if; | ||
| 386 | then | ||
| 387 | outExp; | ||
| 388 | |||
| 389 | else exp; | ||
| 390 | end match; | ||
| 391 | end inlineFunctions_traverser; | ||
| 392 | |||
| 393 | function collectFunctions | ||
| 394 | input Expression exp; | ||
| 395 | input UnorderedSet<Function> funcs; | ||
| 396 | algorithm | ||
| 397 | () := match exp | ||
| 398 | case Expression.CALL() | ||
| 399 | algorithm | ||
| 400 | 1 | collectFunction(Call.typedFunction(exp.call), funcs); | |
| 401 | then | ||
| 402 | (); | ||
| 403 | |||
| 404 | else (); | ||
| 405 | end match; | ||
| 406 | end collectFunctions; | ||
| 407 | |||
| 408 | function collectFunction | ||
| 409 | input Function fn; | ||
| 410 | input UnorderedSet<Function> funcs; | ||
| 411 | algorithm | ||
| 412 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
|
2 | if not Function.isBuiltin(fn) then |
| 413 | 1 | UnorderedSet.add(fn, funcs); | |
| 414 | |||
| 415 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | for fn_der in fn.derivatives loop |
| 416 | ✗ | for der_fn in Function.getCachedFuncs(InstNode.borrow(fn_der.derivativeFn)) loop | |
| 417 | ✗ | UnorderedSet.add(der_fn, funcs); | |
| 418 | end for; | ||
| 419 | end for; | ||
| 420 | |||
| 421 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
|
2 | for fn_inv in fn.inverses loop |
| 422 | ✗ | UnorderedSet.add(FunctionInverse.getFunction(fn_inv), funcs); | |
| 423 | end for; | ||
| 424 | end if; | ||
| 425 | end collectFunction; | ||
| 426 | |||
| 427 | function collectFlatTypes | ||
| 428 | input FlatModel flatModel; | ||
| 429 | input list<Function> functions; | ||
| 430 | output list<Type> outTypes; | ||
| 431 | protected | ||
| 432 | TypeMap types; | ||
| 433 | algorithm | ||
| 434 | 32 | types := UnorderedMap.new<Type>(AbsynUtil.pathHash, AbsynUtil.pathEqual); | |
| 435 | 32 | List.map1_0(flatModel.variables, collectVariableFlatTypes, types); | |
| 436 | 32 | List.map1_0(flatModel.equations, collectEquationFlatTypes, types); | |
| 437 | 32 | List.map1_0(flatModel.initialEquations, collectEquationFlatTypes, types); | |
| 438 | 32 | List.map1_0(flatModel.algorithms, collectAlgorithmFlatTypes, types); | |
| 439 | 32 | List.map1_0(flatModel.initialAlgorithms, collectAlgorithmFlatTypes, types); | |
| 440 | 32 | List.map1_0(functions, collectFunctionFlatTypes, types); | |
| 441 | 32 | outTypes := UnorderedMap.valueList(types); | |
| 442 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 32 times.
|
60 | outTypes := list(typeFlatType(ty) for ty in outTypes); |
| 443 | end collectFlatTypes; | ||
| 444 | |||
| 445 | function collectVariableFlatTypes | ||
| 446 | input Variable var; | ||
| 447 | input TypeMap types; | ||
| 448 | algorithm | ||
| 449 | 847 | collectFlatType(var.ty, types); | |
| 450 | 847 | collectBindingFlatTypes(var.binding, types); | |
| 451 | |||
| 452 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 847 times.
|
882 | for attr in var.typeAttributes loop |
| 453 | 35 | collectBindingFlatTypes(Util.tuple22(attr), types); | |
| 454 | end for; | ||
| 455 | end collectVariableFlatTypes; | ||
| 456 | |||
| 457 | function collectFlatType | ||
| 458 | input Type ty; | ||
| 459 | input TypeMap types; | ||
| 460 | algorithm | ||
| 461 | () := match ty | ||
| 462 | case Type.ENUMERATION() | ||
| 463 | guard not Type.isBuiltinEnumeration(ty) | ||
| 464 | algorithm | ||
| 465 | 7 | UnorderedMap.tryAdd(ty.typePath, ty, types); | |
| 466 | then | ||
| 467 | (); | ||
| 468 | |||
| 469 | case Type.ARRAY() | ||
| 470 | algorithm | ||
| 471 | 852 | Dimension.foldExpList(ty.dimensions, collectExpFlatTypes_traverse, types); | |
| 472 | 852 | collectFlatType(ty.elementType, types); | |
| 473 | then | ||
| 474 | (); | ||
| 475 | |||
| 476 | case Type.COMPLEX(complexTy = ComplexType.RECORD()) | ||
| 477 | algorithm | ||
| 478 | 430 | UnorderedMap.tryAdd(InstNode.scopePath(Type.complexNode(ty)), ty, types); | |
| 479 | then | ||
| 480 | (); | ||
| 481 | |||
| 482 | case Type.COMPLEX(complexTy = ComplexType.EXTERNAL_OBJECT()) | ||
| 483 | algorithm | ||
| 484 | ✗ | UnorderedMap.tryAdd(InstNode.scopePath(Type.complexNode(ty)), ty, types); | |
| 485 | then | ||
| 486 | (); | ||
| 487 | |||
| 488 | case Type.FUNCTION(fnType = NFType.FunctionType.FUNCTIONAL_PARAMETER) | ||
| 489 | algorithm | ||
| 490 | ✗ | UnorderedMap.tryAdd(InstNode.scopePath(InstNode.fromHandle(ty.fn.node)), ty, types); | |
| 491 | then | ||
| 492 | (); | ||
| 493 | |||
| 494 | else (); | ||
| 495 | end match; | ||
| 496 | end collectFlatType; | ||
| 497 | |||
| 498 | function collectBindingFlatTypes | ||
| 499 | input Binding binding; | ||
| 500 | input TypeMap types; | ||
| 501 | algorithm | ||
| 502 |
2/2✓ Branch 1 taken 738 times.
✓ Branch 2 taken 234 times.
|
972 | if Binding.isExplicitlyBound(binding) then |
| 503 | 234 | collectExpFlatTypes(Binding.getTypedExp(binding), types); | |
| 504 | end if; | ||
| 505 | end collectBindingFlatTypes; | ||
| 506 | |||
| 507 | function collectEquationFlatTypes | ||
| 508 | input Equation eq; | ||
| 509 | input TypeMap types; | ||
| 510 | algorithm | ||
| 511 | () := match eq | ||
| 512 | case Equation.EQUALITY() | ||
| 513 | algorithm | ||
| 514 | 356 | collectExpFlatTypes(eq.lhs, types); | |
| 515 | 356 | collectExpFlatTypes(eq.rhs, types); | |
| 516 | 356 | collectFlatType(eq.ty, types); | |
| 517 | then | ||
| 518 | (); | ||
| 519 | |||
| 520 | case Equation.FOR() | ||
| 521 | algorithm | ||
| 522 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
|
18 | if isSome(eq.range) then |
| 523 | 18 | collectExpFlatTypes(Util.getOption(eq.range), types); | |
| 524 | end if; | ||
| 525 | |||
| 526 | 18 | List.map1_0(eq.body, collectEquationFlatTypes, types); | |
| 527 | then | ||
| 528 | (); | ||
| 529 | |||
| 530 | case Equation.IF() | ||
| 531 | algorithm | ||
| 532 | 1 | List.map1_0(eq.branches, collectEqBranchFlatTypes, types); | |
| 533 | then | ||
| 534 | (); | ||
| 535 | |||
| 536 | case Equation.WHEN() | ||
| 537 | algorithm | ||
| 538 | ✗ | List.map1_0(eq.branches, collectEqBranchFlatTypes, types); | |
| 539 | then | ||
| 540 | (); | ||
| 541 | |||
| 542 | case Equation.ASSERT() | ||
| 543 | algorithm | ||
| 544 | ✗ | collectExpFlatTypes(eq.condition, types); | |
| 545 | ✗ | collectExpFlatTypes(eq.message, types); | |
| 546 | ✗ | collectExpFlatTypes(eq.level, types); | |
| 547 | then | ||
| 548 | (); | ||
| 549 | |||
| 550 | case Equation.TERMINATE() | ||
| 551 | algorithm | ||
| 552 | ✗ | collectExpFlatTypes(eq.message, types); | |
| 553 | then | ||
| 554 | (); | ||
| 555 | |||
| 556 | case Equation.REINIT() | ||
| 557 | algorithm | ||
| 558 | ✗ | collectExpFlatTypes(eq.reinitExp, types); | |
| 559 | then | ||
| 560 | (); | ||
| 561 | |||
| 562 | case Equation.NORETCALL() | ||
| 563 | algorithm | ||
| 564 | ✗ | collectExpFlatTypes(eq.exp, types); | |
| 565 | then | ||
| 566 | (); | ||
| 567 | |||
| 568 | else (); | ||
| 569 | end match; | ||
| 570 | end collectEquationFlatTypes; | ||
| 571 | |||
| 572 | function collectEqBranchFlatTypes | ||
| 573 | input Equation.Branch branch; | ||
| 574 | input TypeMap types; | ||
| 575 | algorithm | ||
| 576 | () := match branch | ||
| 577 | case Equation.Branch.BRANCH() | ||
| 578 | algorithm | ||
| 579 | 3 | collectExpFlatTypes(branch.condition, types); | |
| 580 | 3 | List.map1_0(branch.body, collectEquationFlatTypes, types); | |
| 581 | then | ||
| 582 | (); | ||
| 583 | |||
| 584 | else (); | ||
| 585 | end match; | ||
| 586 | end collectEqBranchFlatTypes; | ||
| 587 | |||
| 588 | function collectAlgorithmFlatTypes | ||
| 589 | input Algorithm alg; | ||
| 590 | input TypeMap types; | ||
| 591 | algorithm | ||
| 592 | ✗ | collectStatementsFlatTypes(alg.statements, types); | |
| 593 | end collectAlgorithmFlatTypes; | ||
| 594 | |||
| 595 | function collectStatementsFlatTypes | ||
| 596 | input list<Statement> statements; | ||
| 597 | input TypeMap types; | ||
| 598 | algorithm | ||
| 599 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 27 times.
|
31 | for s in statements loop |
| 600 | 4 | collectStatementFlatTypes(s, types); | |
| 601 | end for; | ||
| 602 | end collectStatementsFlatTypes; | ||
| 603 | |||
| 604 | function collectStatementFlatTypes | ||
| 605 | input Statement stmt; | ||
| 606 | input TypeMap types; | ||
| 607 | algorithm | ||
| 608 | () := match stmt | ||
| 609 | case Statement.ASSIGNMENT() | ||
| 610 | algorithm | ||
| 611 | 4 | collectExpFlatTypes(stmt.lhs, types); | |
| 612 | 4 | collectExpFlatTypes(stmt.rhs, types); | |
| 613 | 4 | collectFlatType(stmt.ty, types); | |
| 614 | then | ||
| 615 | (); | ||
| 616 | |||
| 617 | case Statement.FOR() | ||
| 618 | algorithm | ||
| 619 | ✗ | collectStatementsFlatTypes(stmt.body, types); | |
| 620 | ✗ | collectExpFlatTypes(Util.getOption(stmt.range), types); | |
| 621 | then | ||
| 622 | (); | ||
| 623 | |||
| 624 | case Statement.IF() | ||
| 625 | algorithm | ||
| 626 | ✗ | List.map1_0(stmt.branches, collectStmtBranchFlatTypes, types); | |
| 627 | then | ||
| 628 | (); | ||
| 629 | |||
| 630 | case Statement.WHEN() | ||
| 631 | algorithm | ||
| 632 | ✗ | List.map1_0(stmt.branches, collectStmtBranchFlatTypes, types); | |
| 633 | then | ||
| 634 | (); | ||
| 635 | |||
| 636 | case Statement.ASSERT() | ||
| 637 | algorithm | ||
| 638 | ✗ | collectExpFlatTypes(stmt.condition, types); | |
| 639 | ✗ | collectExpFlatTypes(stmt.message, types); | |
| 640 | ✗ | collectExpFlatTypes(stmt.level, types); | |
| 641 | then | ||
| 642 | (); | ||
| 643 | |||
| 644 | case Statement.TERMINATE() | ||
| 645 | algorithm | ||
| 646 | ✗ | collectExpFlatTypes(stmt.message, types); | |
| 647 | then | ||
| 648 | (); | ||
| 649 | |||
| 650 | case Statement.REINIT() | ||
| 651 | algorithm | ||
| 652 | ✗ | collectExpFlatTypes(stmt.cref, types); | |
| 653 | ✗ | collectExpFlatTypes(stmt.reinitExp, types); | |
| 654 | then | ||
| 655 | (); | ||
| 656 | |||
| 657 | case Statement.NORETCALL() | ||
| 658 | algorithm | ||
| 659 | ✗ | collectExpFlatTypes(stmt.exp, types); | |
| 660 | then | ||
| 661 | (); | ||
| 662 | |||
| 663 | case Statement.WHILE() | ||
| 664 | algorithm | ||
| 665 | ✗ | collectExpFlatTypes(stmt.condition, types); | |
| 666 | ✗ | collectStatementsFlatTypes(stmt.body, types); | |
| 667 | then | ||
| 668 | (); | ||
| 669 | |||
| 670 | else (); | ||
| 671 | end match; | ||
| 672 | end collectStatementFlatTypes; | ||
| 673 | |||
| 674 | function collectStmtBranchFlatTypes | ||
| 675 | input tuple<Expression, list<Statement>> branch; | ||
| 676 | input TypeMap types; | ||
| 677 | algorithm | ||
| 678 | ✗ | collectExpFlatTypes(Util.tuple21(branch), types); | |
| 679 | ✗ | collectStatementsFlatTypes(Util.tuple22(branch), types); | |
| 680 | end collectStmtBranchFlatTypes; | ||
| 681 | |||
| 682 | function collectExpFlatTypes | ||
| 683 | input Expression exp; | ||
| 684 | input TypeMap types; | ||
| 685 | algorithm | ||
| 686 | 975 | Expression.fold(exp, collectExpFlatTypes_traverse, types); | |
| 687 | end collectExpFlatTypes; | ||
| 688 | |||
| 689 | function collectExpFlatTypes_traverse | ||
| 690 | input Expression exp; | ||
| 691 | input output TypeMap types; | ||
| 692 | algorithm | ||
| 693 | 3433 | collectFlatType(Expression.typeOf(exp), types); | |
| 694 | end collectExpFlatTypes_traverse; | ||
| 695 | |||
| 696 | function collectFunctionFlatTypes | ||
| 697 | input Function fn; | ||
| 698 | input TypeMap types; | ||
| 699 | algorithm | ||
| 700 | 28 | ClassTree.applyComponents(Class.classTree(InstNode.getClass(InstNode.fromHandle(fn.node))), | |
| 701 | function collectComponentFlatTypes(types = types)); | ||
| 702 | |||
| 703 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 27 times.
|
28 | if not Function.isExternal(fn) then |
| 704 | 27 | collectStatementsFlatTypes(Function.getBody(fn), types); | |
| 705 | end if; | ||
| 706 | end collectFunctionFlatTypes; | ||
| 707 | |||
| 708 | function collectComponentFlatTypes | ||
| 709 | input InstNode component; | ||
| 710 | input TypeMap types; | ||
| 711 | protected | ||
| 712 | Component comp; | ||
| 713 | algorithm | ||
| 714 | 90 | comp := InstNode.component(component); | |
| 715 | 90 | collectFlatType(Component.getType(comp), types); | |
| 716 | 90 | collectBindingFlatTypes(Component.getBinding(comp), types); | |
| 717 | end collectComponentFlatTypes; | ||
| 718 | |||
| 719 | function reconstructRecordInstances | ||
| 720 | input list<Variable> variables; | ||
| 721 | output list<Variable> outVariables = {}; | ||
| 722 | protected | ||
| 723 | list<Variable> rest_vars = variables, record_vars; | ||
| 724 | Variable var; | ||
| 725 | ComponentRef parent_cr; | ||
| 726 | Type parent_ty; | ||
| 727 | Integer field_count; | ||
| 728 | algorithm | ||
| 729 |
2/2✓ Branch 0 taken 826 times.
✓ Branch 1 taken 27 times.
|
853 | while not listEmpty(rest_vars) loop |
| 730 | 826 | var :: rest_vars := rest_vars; | |
| 731 | 826 | parent_cr := ComponentRef.rest(var.name); | |
| 732 | |||
| 733 |
2/2✓ Branch 1 taken 789 times.
✓ Branch 2 taken 37 times.
|
826 | if not ComponentRef.isEmpty(parent_cr) then |
| 734 | 789 | parent_ty := ComponentRef.nodeType(parent_cr); | |
| 735 | |||
| 736 |
2/2✓ Branch 1 taken 97 times.
✓ Branch 2 taken 692 times.
|
789 | if Type.isRecord(parent_ty) then |
| 737 | 97 | field_count := listLength(Type.recordFields(parent_ty)); | |
| 738 | 97 | (record_vars, rest_vars) := List.split(rest_vars, field_count - 1); | |
| 739 | record_vars := var :: record_vars; | ||
| 740 | 97 | var := reconstructRecordInstance(parent_cr, record_vars); | |
| 741 | end if; | ||
| 742 | end if; | ||
| 743 | |||
| 744 | outVariables := var :: outVariables; | ||
| 745 | end while; | ||
| 746 | |||
| 747 | 27 | outVariables := listReverseInPlace(outVariables); | |
| 748 | end reconstructRecordInstances; | ||
| 749 | |||
| 750 | function reconstructRecordInstance | ||
| 751 | "Reconstructs a record instance variable from its individual field variables." | ||
| 752 | input ComponentRef recordName; | ||
| 753 | input list<Variable> variables; | ||
| 754 | output Variable recordVar; | ||
| 755 | protected | ||
| 756 | InstNode record_node; | ||
| 757 | Component record_comp; | ||
| 758 | Type record_ty; | ||
| 759 | list<Expression> field_exps; | ||
| 760 | Expression record_exp; | ||
| 761 | Binding record_binding; | ||
| 762 | algorithm | ||
| 763 | 97 | record_node := ComponentRef.node(recordName); | |
| 764 | 97 | record_comp := InstNode.component(record_node); | |
| 765 | 97 | record_ty := ComponentRef.nodeType(recordName); | |
| 766 | |||
| 767 | // Reconstruct the record instance binding if possible. If any field is | ||
| 768 | // missing a binding we assume that the record instance didn't have a | ||
| 769 | // binding in the first place, or that the binding was moved to an equation | ||
| 770 | // during flattening. | ||
| 771 | field_exps := {}; | ||
| 772 |
2/2✓ Branch 0 taken 150 times.
✓ Branch 1 taken 20 times.
|
170 | for v in variables loop |
| 773 |
2/2✓ Branch 1 taken 73 times.
✓ Branch 2 taken 77 times.
|
150 | if Binding.hasExp(v.binding) then |
| 774 | 73 | field_exps := Binding.getExp(v.binding) :: field_exps; | |
| 775 | else | ||
| 776 | field_exps := {}; | ||
| 777 | break; | ||
| 778 | end if; | ||
| 779 | end for; | ||
| 780 | |||
| 781 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 77 times.
|
97 | if listEmpty(field_exps) then |
| 782 | record_binding := NFBinding.EMPTY_BINDING; | ||
| 783 | else | ||
| 784 | 20 | field_exps := listReverseInPlace(field_exps); | |
| 785 | 20 | record_exp := Expression.makeRecord(InstNode.scopePath(InstNode.classScope(record_node)), record_ty, field_exps); | |
| 786 | 20 | record_binding := Binding.makeFlat(record_exp, Component.variability(record_comp), NFBinding.Source.GENERATED); | |
| 787 | end if; | ||
| 788 | |||
| 789 | 97 | recordVar := Variable.VARIABLE(recordName, record_ty, record_binding, InstNode.visibility(record_node), | |
| 790 | Component.getAttributes(record_comp), {}, variables, Component.comment(record_comp), InstNode.info(record_node), NFBackendExtension.DUMMY_BACKEND_INFO); | ||
| 791 | end reconstructRecordInstance; | ||
| 792 | |||
| 793 | function typeFlatType | ||
| 794 | input output Type ty; | ||
| 795 | algorithm | ||
| 796 | () := match ty | ||
| 797 | case Type.COMPLEX(complexTy = ComplexType.RECORD()) | ||
| 798 | algorithm | ||
| 799 | 26 | Typing.typeBindings(Type.complexNode(ty), NFInstContext.CLASS); | |
| 800 | then | ||
| 801 | (); | ||
| 802 | |||
| 803 | else (); | ||
| 804 | end match; | ||
| 805 | end typeFlatType; | ||
| 806 | |||
| 807 | protected | ||
| 808 | type ObfuscationMap = UnorderedMap<InstNode, String>; | ||
| 809 | |||
| 810 | public | ||
| 811 | function obfuscate | ||
| 812 | input output FlatModel flatModel; | ||
| 813 | protected | ||
| 814 | ObfuscationMap obfuscation_map; | ||
| 815 | Boolean only_encrypted; | ||
| 816 | algorithm | ||
| 817 |
2/4✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
|
7 | only_encrypted := Flags.getConfigString(Flags.OBFUSCATE) == "encrypted"; |
| 818 | 7 | obfuscation_map := UnorderedMap.new<String>(InstNode.hash, InstNode.refEqual); | |
| 819 | |||
| 820 |
2/2✓ Branch 0 taken 12330 times.
✓ Branch 1 taken 7 times.
|
12337 | for v in flatModel.variables loop |
| 821 | 12330 | addObfuscatedVariable(v, only_encrypted, obfuscation_map); | |
| 822 | end for; | ||
| 823 | |||
| 824 |
4/4✓ Branch 0 taken 12330 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 12330 times.
✓ Branch 3 taken 7 times.
|
12344 | flatModel.variables := list(obfuscateVariable(v, obfuscation_map) for v in flatModel.variables); |
| 825 | 7 | flatModel := mapEquations(flatModel, function obfuscateEquation(obfuscationMap = obfuscation_map)); | |
| 826 | 7 | flatModel := mapAlgorithms(flatModel, function obfuscateAlgorithm(obfuscationMap = obfuscation_map)); | |
| 827 | end obfuscate; | ||
| 828 | |||
| 829 | function addObfuscatedVariable | ||
| 830 | input Variable var; | ||
| 831 | input Boolean onlyEncrypted; | ||
| 832 | input ObfuscationMap obfuscationMap; | ||
| 833 | protected | ||
| 834 | list<InstNode> nodes; | ||
| 835 | algorithm | ||
| 836 |
3/6✓ Branch 1 taken 10453 times.
✓ Branch 2 taken 1877 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1877 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
12330 | if Variable.isProtected(var) and (not onlyEncrypted or Variable.isEncrypted(var)) then |
| 837 | 1877 | nodes := ComponentRef.nodes(var.name); | |
| 838 | 1877 | nodes := List.trim(nodes, InstNode.isPublic); | |
| 839 | |||
| 840 |
2/2✓ Branch 0 taken 1877 times.
✓ Branch 1 taken 1877 times.
|
3754 | for node in nodes loop |
| 841 | 1877 | UnorderedMap.tryAdd(node, "n" + String(UnorderedMap.size(obfuscationMap) + 1), obfuscationMap); | |
| 842 | end for; | ||
| 843 | end if; | ||
| 844 | end addObfuscatedVariable; | ||
| 845 | |||
| 846 | function obfuscateVariable | ||
| 847 | input output Variable var; | ||
| 848 | input ObfuscationMap obfuscationMap; | ||
| 849 | algorithm | ||
| 850 | 12330 | var.name := obfuscateCref(var.name, obfuscationMap); | |
| 851 | 12330 | var.comment := obfuscateComment(var.comment, ComponentRef.node(var.name), | |
| 852 | obfuscationMap, stripComment = not Variable.isAccessible(var)); | ||
| 853 | 12330 | var := Variable.mapExpShallow(var, function obfuscateExp(obfuscationMap = obfuscationMap)); | |
| 854 | end obfuscateVariable; | ||
| 855 | |||
| 856 | function obfuscateCref | ||
| 857 | input output ComponentRef cref; | ||
| 858 | input ObfuscationMap obfuscationMap; | ||
| 859 | output Boolean insideRecord = false; | ||
| 860 | protected | ||
| 861 | Option<String> name; | ||
| 862 | ComponentRef rest_cref; | ||
| 863 | algorithm | ||
| 864 | () := match cref | ||
| 865 | case ComponentRef.CREF() | ||
| 866 | algorithm | ||
| 867 | 136992 | (rest_cref, insideRecord) := obfuscateCref(cref.restCref, obfuscationMap); | |
| 868 |
2/2✓ Branch 0 taken 132764 times.
✓ Branch 1 taken 4228 times.
|
136992 | cref.restCref := rest_cref; |
| 869 | |||
| 870 | // Only obfuscate variables that do not belong to a record instance, | ||
| 871 | // record field names need to be kept to keep them consistent with the | ||
| 872 | // record constructors. | ||
| 873 |
2/2✓ Branch 0 taken 132764 times.
✓ Branch 1 taken 4228 times.
|
136992 | if not insideRecord then |
| 874 | 132764 | name := UnorderedMap.get(ComponentRef.node(cref), obfuscationMap); | |
| 875 | |||
| 876 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 132764 times.
✓ Branch 2 taken 6223 times.
✓ Branch 3 taken 126541 times.
|
132764 | if isSome(name) then |
| 877 | 6223 | cref.node := ComponentRef.storeNode( | |
| 878 | InstNode.rename(Util.getOption(name), ComponentRef.node(cref))); | ||
| 879 | end if; | ||
| 880 | end if; | ||
| 881 | |||
| 882 | 136992 | insideRecord := InstNode.isRecord(ComponentRef.node(cref)); | |
| 883 | |||
| 884 |
4/4✓ Branch 0 taken 39909 times.
✓ Branch 1 taken 136992 times.
✓ Branch 2 taken 39909 times.
✓ Branch 3 taken 136992 times.
|
313893 | cref.subscripts := list(Subscript.mapShallowExp(s, |
| 885 | function obfuscateExp(obfuscationMap = obfuscationMap)) for s in cref.subscripts); | ||
| 886 | then | ||
| 887 | (); | ||
| 888 | |||
| 889 | else (); | ||
| 890 | end match; | ||
| 891 | end obfuscateCref; | ||
| 892 | |||
| 893 | function obfuscateExp | ||
| 894 | input output Expression exp; | ||
| 895 | input ObfuscationMap obfuscationMap; | ||
| 896 | algorithm | ||
| 897 | 109930 | exp := Expression.map(exp, function obfuscateExp_impl(obfuscationMap = obfuscationMap)); | |
| 898 | end obfuscateExp; | ||
| 899 | |||
| 900 | function obfuscateExpOpt | ||
| 901 | input output Option<Expression> exp; | ||
| 902 | input ObfuscationMap obfuscationMap; | ||
| 903 | algorithm | ||
| 904 | ✗ | if isSome(exp) then | |
| 905 | ✗ | exp := SOME(obfuscateExp(Util.getOption(exp), obfuscationMap)); | |
| 906 | end if; | ||
| 907 | end obfuscateExpOpt; | ||
| 908 | |||
| 909 | function obfuscateExp_impl | ||
| 910 | input output Expression exp; | ||
| 911 | input ObfuscationMap obfuscationMap; | ||
| 912 | algorithm | ||
| 913 | () := match exp | ||
| 914 | case Expression.CREF() | ||
| 915 | algorithm | ||
| 916 | 39623 | exp.cref := obfuscateCref(exp.cref, obfuscationMap); | |
| 917 | then | ||
| 918 | (); | ||
| 919 | |||
| 920 | else (); | ||
| 921 | end match; | ||
| 922 | end obfuscateExp_impl; | ||
| 923 | |||
| 924 | function obfuscateEquation | ||
| 925 | input output Equation eq; | ||
| 926 | input ObfuscationMap obfuscationMap; | ||
| 927 | algorithm | ||
| 928 | 9100 | eq := Equation.setSource(obfuscateSource(Equation.source(eq), Equation.scope(eq), obfuscationMap), eq); | |
| 929 | 9100 | eq := Equation.mapExpShallow(eq, function obfuscateExp(obfuscationMap = obfuscationMap)); | |
| 930 | end obfuscateEquation; | ||
| 931 | |||
| 932 | function obfuscateAlgorithm | ||
| 933 | input output Algorithm alg; | ||
| 934 | input ObfuscationMap obfuscationMap; | ||
| 935 | algorithm | ||
| 936 | ✗ | alg.source := obfuscateSource(alg.source, InstNode.fromCell(alg.scope), obfuscationMap); | |
| 937 | alg.inputs := list(obfuscateCref(e, obfuscationMap) for e in alg.inputs); | ||
| 938 | alg.outputs := list(obfuscateCref(e, obfuscationMap) for e in alg.outputs); | ||
| 939 | alg.statements := list(Statement.map(s, | ||
| 940 | function obfuscateStatement(scope = InstNode.fromCell(alg.scope), obfuscationMap = obfuscationMap)) for s in alg.statements); | ||
| 941 | end obfuscateAlgorithm; | ||
| 942 | |||
| 943 | function obfuscateStatement | ||
| 944 | input output Statement stmt; | ||
| 945 | input InstNode scope; | ||
| 946 | input ObfuscationMap obfuscationMap; | ||
| 947 | algorithm | ||
| 948 | ✗ | stmt := Statement.setSource(obfuscateSource(Statement.source(stmt), scope, obfuscationMap), stmt); | |
| 949 | ✗ | stmt := Statement.mapExpShallow(stmt, function obfuscateExp(obfuscationMap = obfuscationMap)); | |
| 950 | end obfuscateStatement; | ||
| 951 | |||
| 952 | function obfuscateSource | ||
| 953 | input output DAE.ElementSource source; | ||
| 954 | input InstNode scope; | ||
| 955 | input ObfuscationMap obfuscationMap; | ||
| 956 | algorithm | ||
| 957 |
4/4✓ Branch 0 taken 8107 times.
✓ Branch 1 taken 9100 times.
✓ Branch 2 taken 8107 times.
✓ Branch 3 taken 9100 times.
|
17207 | source.comment := list(obfuscateComment(c, scope, obfuscationMap) for c in source.comment); |
| 958 | end obfuscateSource; | ||
| 959 | |||
| 960 | function obfuscateCommentOpt | ||
| 961 | input output Option<SCode.Comment> comment; | ||
| 962 | input InstNode scope; | ||
| 963 | input ObfuscationMap obfuscationMap; | ||
| 964 | input Boolean stripComment = true; | ||
| 965 | algorithm | ||
| 966 | ✗ | comment := Util.applyOption(comment, | |
| 967 | function obfuscateComment(scope = scope, obfuscationMap = obfuscationMap, stripComment = stripComment)); | ||
| 968 | end obfuscateCommentOpt; | ||
| 969 | |||
| 970 | function obfuscateComment | ||
| 971 | input output SCode.Comment comment; | ||
| 972 | input InstNode scope; | ||
| 973 | input ObfuscationMap obfuscationMap; | ||
| 974 | input Boolean stripComment = true; | ||
| 975 | algorithm | ||
| 976 | 20437 | comment.annotation_ := obfuscateAnnotationOpt(comment.annotation_, scope, obfuscationMap); | |
| 977 | |||
| 978 |
2/2✓ Branch 0 taken 12330 times.
✓ Branch 1 taken 8107 times.
|
20437 | if stripComment then |
| 979 | 8107 | comment.comment := NONE(); | |
| 980 | end if; | ||
| 981 | end obfuscateComment; | ||
| 982 | |||
| 983 | function obfuscateAnnotationOpt | ||
| 984 | input output Option<SCode.Annotation> ann; | ||
| 985 | input InstNode scope; | ||
| 986 | input ObfuscationMap obfuscationMap; | ||
| 987 | algorithm | ||
| 988 | 20437 | ann := Util.applyOption(ann, | |
| 989 | function obfuscateAnnotation(scope = scope, obfuscationMap = obfuscationMap)); | ||
| 990 | end obfuscateAnnotationOpt; | ||
| 991 | |||
| 992 | function obfuscateAnnotation | ||
| 993 | input output SCode.Annotation ann; | ||
| 994 | input InstNode scope; | ||
| 995 | input ObfuscationMap obfuscationMap; | ||
| 996 | algorithm | ||
| 997 | 2374 | ann.modification := obfuscateAnnotationMod(ann.modification, scope, obfuscationMap); | |
| 998 | end obfuscateAnnotation; | ||
| 999 | |||
| 1000 | function obfuscateAnnotationMod | ||
| 1001 | input output SCode.Mod mod; | ||
| 1002 | input InstNode scope; | ||
| 1003 | input ObfuscationMap obfuscationMap; | ||
| 1004 | algorithm | ||
| 1005 | () := match mod | ||
| 1006 | case SCode.Mod.MOD() | ||
| 1007 | algorithm | ||
| 1008 |
6/6✓ Branch 1 taken 2234 times.
✓ Branch 2 taken 1285 times.
✓ Branch 3 taken 3519 times.
✓ Branch 4 taken 3659 times.
✓ Branch 5 taken 1285 times.
✓ Branch 6 taken 3659 times.
|
10837 | mod.subModLst := list(obfuscateAnnotationSubMod(s, scope, obfuscationMap) |
| 1009 | for s guard isAllowedAnnotation(s) in mod.subModLst); | ||
| 1010 | 3659 | mod.binding := obfuscateAbsynExpOpt(mod.binding, scope, obfuscationMap); | |
| 1011 | then | ||
| 1012 | (); | ||
| 1013 | |||
| 1014 | else (); | ||
| 1015 | end match; | ||
| 1016 | end obfuscateAnnotationMod; | ||
| 1017 | |||
| 1018 | function isAllowedAnnotation | ||
| 1019 | input SCode.SubMod mod; | ||
| 1020 | output Boolean allowed; | ||
| 1021 | algorithm | ||
| 1022 | allowed := match mod.ident | ||
| 1023 | case "Icon" then false; | ||
| 1024 | case "Diagram" then false; | ||
| 1025 | case "Dialog" then false; | ||
| 1026 | case "IconMap" then false; | ||
| 1027 | case "DiagramMap" then false; | ||
| 1028 | case "Placement" then false; | ||
| 1029 | case "Text" then false; | ||
| 1030 | case "Line" then false; | ||
| 1031 | case "defaultComponentName" then false; | ||
| 1032 | case "defaultComponentPrefixes" then false; | ||
| 1033 | case "missingInnerMessage" then false; | ||
| 1034 | case "obsolete" then false; | ||
| 1035 | case "unassignedMessage" then false; | ||
| 1036 | case "Protection" then false; | ||
| 1037 | case "Authorization" then false; | ||
| 1038 | 1285 | else not StringUtil.startsWith(mod.ident, "__"); | |
| 1039 | end match; | ||
| 1040 | end isAllowedAnnotation; | ||
| 1041 | |||
| 1042 | function obfuscateAnnotationSubMod | ||
| 1043 | input output SCode.SubMod mod; | ||
| 1044 | input InstNode scope; | ||
| 1045 | input ObfuscationMap obfuscationMap; | ||
| 1046 | algorithm | ||
| 1047 | 1285 | mod.mod := obfuscateAnnotationMod(mod.mod, scope, obfuscationMap); | |
| 1048 | end obfuscateAnnotationSubMod; | ||
| 1049 | |||
| 1050 | function obfuscateAbsynExpOpt | ||
| 1051 | input output Option<Absyn.Exp> exp; | ||
| 1052 | input InstNode scope; | ||
| 1053 | input ObfuscationMap obfuscationMap; | ||
| 1054 | algorithm | ||
| 1055 | 3659 | exp := Util.applyOption(exp, | |
| 1056 | function obfuscateAbsynExp(scope = scope, obfuscationMap = obfuscationMap)); | ||
| 1057 | end obfuscateAbsynExpOpt; | ||
| 1058 | |||
| 1059 | function obfuscateAbsynExp | ||
| 1060 | input output Absyn.Exp exp; | ||
| 1061 | input InstNode scope; | ||
| 1062 | input ObfuscationMap obfuscationMap; | ||
| 1063 | algorithm | ||
| 1064 | 1229 | exp := AbsynUtil.traverseExp(exp, function obfuscateAbsynExpTraverse(scope = scope), obfuscationMap); | |
| 1065 | end obfuscateAbsynExp; | ||
| 1066 | |||
| 1067 | function obfuscateAbsynExpTraverse | ||
| 1068 | input output Absyn.Exp exp; | ||
| 1069 | input InstNode scope; | ||
| 1070 | input output ObfuscationMap obfuscationMap; | ||
| 1071 | algorithm | ||
| 1072 | () := match exp | ||
| 1073 | case Absyn.Exp.CREF() | ||
| 1074 | algorithm | ||
| 1075 | ✗ | exp.componentRef := obfuscateAbsynCref(exp.componentRef, scope, obfuscationMap); | |
| 1076 | then | ||
| 1077 | (); | ||
| 1078 | |||
| 1079 | else (); | ||
| 1080 | end match; | ||
| 1081 | end obfuscateAbsynExpTraverse; | ||
| 1082 | |||
| 1083 | function obfuscateAbsynCref | ||
| 1084 | input output Absyn.ComponentRef cref; | ||
| 1085 | input InstNode scope; | ||
| 1086 | input ObfuscationMap obfuscationMap; | ||
| 1087 | protected | ||
| 1088 | ComponentRef inst_cref; | ||
| 1089 | list<InstNode> nodes; | ||
| 1090 | algorithm | ||
| 1091 | ✗ | ErrorExt.setCheckpoint(getInstanceName()); | |
| 1092 | try | ||
| 1093 | ✗ | inst_cref := Lookup.lookupCref(cref, scope, NFInstContext.RELAXED); | |
| 1094 | ✗ | nodes := list(ComponentRef.node(c) for c in ComponentRef.toListReverse(inst_cref, includeScope = false)); | |
| 1095 | ✗ | cref := obfuscateAbsynCref2(cref, nodes, obfuscationMap); | |
| 1096 | else | ||
| 1097 | end try; | ||
| 1098 | ✗ | ErrorExt.rollBack(getInstanceName()); | |
| 1099 | end obfuscateAbsynCref; | ||
| 1100 | |||
| 1101 | function obfuscateAbsynCref2 | ||
| 1102 | input output Absyn.ComponentRef cref; | ||
| 1103 | input list<InstNode> nodes; | ||
| 1104 | input ObfuscationMap obfuscationMap; | ||
| 1105 | protected | ||
| 1106 | InstNode node; | ||
| 1107 | list<InstNode> rest_nodes; | ||
| 1108 | algorithm | ||
| 1109 | () := match (cref, nodes) | ||
| 1110 | case (Absyn.ComponentRef.CREF_FULLYQUALIFIED(), _) | ||
| 1111 | algorithm | ||
| 1112 | ✗ | cref.componentRef := obfuscateAbsynCref2(cref.componentRef, nodes, obfuscationMap); | |
| 1113 | then | ||
| 1114 | (); | ||
| 1115 | |||
| 1116 | case (Absyn.ComponentRef.CREF_QUAL(), node :: rest_nodes) | ||
| 1117 | guard InstNode.name(node) == cref.name | ||
| 1118 | algorithm | ||
| 1119 | ✗ | cref.name := UnorderedMap.getOrDefault(node, obfuscationMap, cref.name); | |
| 1120 | ✗ | cref.componentRef := obfuscateAbsynCref2(cref.componentRef, rest_nodes, obfuscationMap); | |
| 1121 | then | ||
| 1122 | (); | ||
| 1123 | |||
| 1124 | case (Absyn.ComponentRef.CREF_IDENT(), node :: _) | ||
| 1125 | guard InstNode.name(node) == cref.name | ||
| 1126 | algorithm | ||
| 1127 | ✗ | cref.name := UnorderedMap.getOrDefault(node, obfuscationMap, cref.name); | |
| 1128 | then | ||
| 1129 | (); | ||
| 1130 | |||
| 1131 | else (); | ||
| 1132 | end match; | ||
| 1133 | end obfuscateAbsynCref2; | ||
| 1134 | |||
| 1135 | function hasArrayConnections | ||
| 1136 | input FlatModel flatModel; | ||
| 1137 | input Integer minSize = 100; | ||
| 1138 | output Boolean hasArrays = false; | ||
| 1139 | algorithm | ||
| 1140 | ✗ | for eq in flatModel.equations loop | |
| 1141 | ✗ | if Equation.contains(eq, Equation.isConnect) and Equation.sizeOf(eq) >= minSize then | |
| 1142 | hasArrays := true; | ||
| 1143 | ✗ | return; | |
| 1144 | end if; | ||
| 1145 | end for; | ||
| 1146 | end hasArrayConnections; | ||
| 1147 | |||
| 1148 | function removeNonTopLevelDirections | ||
| 1149 | input output FlatModel flatModel; | ||
| 1150 | algorithm | ||
| 1151 | // Keep the declared directions if --useLocalDirection=true has been set. | ||
| 1152 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1430 times.
|
1430 | if Flags.getConfigBool(Flags.USE_LOCAL_DIRECTION) then |
| 1153 | ✗ | return; | |
| 1154 | end if; | ||
| 1155 | |||
| 1156 |
4/4✓ Branch 0 taken 378211 times.
✓ Branch 1 taken 1430 times.
✓ Branch 2 taken 378211 times.
✓ Branch 3 taken 1430 times.
|
381071 | flatModel.variables := list(Variable.removeNonTopLevelDirection(v) for v in flatModel.variables); |
| 1157 | end removeNonTopLevelDirections; | ||
| 1158 | |||
| 1159 | function moveBindings | ||
| 1160 | "Moves binding equations of variables to the equation section of the flat model." | ||
| 1161 | input output FlatModel flatModel; | ||
| 1162 | protected | ||
| 1163 | list<Variable> vars = {}; | ||
| 1164 | list<Equation> eqs = {}; | ||
| 1165 | algorithm | ||
| 1166 | ✗ | for var in flatModel.variables loop | |
| 1167 | ✗ | (var, eqs) := Variable.moveBinding(var, eqs); | |
| 1168 | vars := var :: vars; | ||
| 1169 | end for; | ||
| 1170 | |||
| 1171 | ✗ | if not listEmpty(eqs) then | |
| 1172 | ✗ | flatModel.variables := listReverseInPlace(vars); | |
| 1173 | flatModel.equations := listAppend(listReverseInPlace(eqs), flatModel.equations); | ||
| 1174 | end if; | ||
| 1175 | end moveBindings; | ||
| 1176 | |||
| 1177 | annotation(__OpenModelica_Interface="nf_frontend"); | ||
| 1178 | end NFFlatModel; | ||
| 1179 |