Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 47.9% 1256 / 0 / 2624
Functions: -% 0 / 1 / 1
Branches: 39.3% 659 / 0 / 1676

OMCompiler/Compiler/Script/CevalScriptBackend.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 CevalScriptBackend
37 "
38 This module handles constant propagation of expressions for scripting
39 functions. This module contains the parts not needed for the
40 bootstrapping.
41 "
42
43 // public imports
44 import Absyn;
45 import ProgramUtil;
46 import AbsynUtil;
47 import AbsynJLDumpTpl;
48 import BackendDAE;
49 import Ceval;
50 import DAE;
51 import FCore;
52 import Interactive;
53 import InteractiveTypes;
54 import Interactive.Access;
55 import InteractiveUtil;
56 import Values;
57 import SimCode;
58 import UnitAbsyn;
59
60 // protected imports
61 protected
62 import AbsynToJulia;
63 import AbsynToSCode;
64 import Autoconf;
65 import BackendDAECreate;
66 import BackendDAEOptimize;
67 import BackendDAEUtil;
68 import BackendDump;
69 import BackendEquation;
70 import BackendVariable;
71 import Binding;
72 import BlockCallRewrite;
73 import CevalScript;
74 import CodegenWasmJit;
75 import CodegenWasmJitFunctions;
76 import CheckModel;
77 import ClassInf;
78 import ClockIndexes;
79 import CodegenFMU;
80 import ComponentReference;
81 protected import ComponentReferenceBasics;
82 import Config;
83 import Conversion;
84 import DAEDump;
85 import DAEQuery;
86 import DAEUtil;
87 import Debug;
88 import DiffAlgorithm;
89 import ContainerImage;
90 import Dump;
91 import Error;
92 import ErrorExt;
93 import ExecStat;
94 import Expression;
95 protected import ExpressionBasics;
96 import FBuiltin;
97 import FGraph;
98 import Figaro;
99 import FindZeroCrossings;
100 import FInst;
101 import Flags;
102 import FlagsUtil;
103 import FlatModel = NFFlatModel;
104 import FMI;
105 import FMIExt;
106 import FunctionTree = NFFlatten.FunctionTree;
107 import GCExt;
108 import GlobalScript;
109 import Graph;
110 import InnerOuter;
111 import Inst;
112 import LexerModelicaDiff;
113 import List;
114 import Lookup;
115 import NFApi;
116 import NFConvertDAE;
117 import NFFlatModel;
118 import NFFlatten;
119 import NFInst;
120 import NFSCodeEnv;
121 import NFSCodeFlatten;
122 import NFSCodeLookup;
123 import NFClassDiagram;
124 import NFDefUseChains;
125 import NFUsedElements;
126 import Obfuscate;
127 import OMGraphics;
128 import PackageManagement;
129 import Parser;
130 import Print;
131 import Refactor;
132 import ReverseLookup;
133 import RewriteRules;
134 import SCode;
135 import SCodeDump;
136 import SCodeUtil;
137 import SemanticVersion;
138 import Settings;
139 import SimCodeMain;
140 import SimCodeFunction;
141 import SimCodeFunctionUtil;
142 import SimCodeUtil;
143 import StateMachineFlatten;
144 import SimpleModelicaParser;
145 import SimulationResults;
146 import StaticScript;
147 import StringUtil;
148 import SymbolicJacobian;
149 import SymbolTable;
150 import System;
151 import TaskGraphResults;
152 import TotalModelDebug;
153 import Tpl;
154 import Types;
155 import Uncertainties;
156 import UnitAbsynBuilder;
157 import UnitParserExt;
158 import UnorderedSet;
159 import Util;
160 import ValuesDump;
161 import ValuesMake;
162 import ValuesUtil;
163 import XMLDump;
164
165 protected constant DAE.Type simulationResultType_rtest = DAE.T_COMPLEX(ClassInf.RECORD(Absyn.IDENT("SimulationResult")),{
166 DAE.TYPES_VAR("resultFile",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),false,NONE()),
167 DAE.TYPES_VAR("simulationOptions",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),false,NONE()),
168 DAE.TYPES_VAR("messages",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),false,NONE())
169 },NONE(), false);
170
171 protected constant DAE.Type simulationResultType_full = DAE.T_COMPLEX(ClassInf.RECORD(Absyn.IDENT("SimulationResult")),{
172 DAE.TYPES_VAR("resultFile",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),false,NONE()),
173 DAE.TYPES_VAR("simulationOptions",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),false,NONE()),
174 DAE.TYPES_VAR("messages",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),false,NONE()),
175 DAE.TYPES_VAR("timeFrontend",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),false,NONE()),
176 DAE.TYPES_VAR("timeBackend",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),false,NONE()),
177 DAE.TYPES_VAR("timeSimCode",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),false,NONE()),
178 DAE.TYPES_VAR("timeTemplates",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),false,NONE()),
179 DAE.TYPES_VAR("timeCompile",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),false,NONE()),
180 DAE.TYPES_VAR("timeSimulation",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),false,NONE()),
181 DAE.TYPES_VAR("timeTotal",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),false,NONE())
182 },NONE(), false);
183
184 protected constant DAE.Type simulationResultType_drModelica = DAE.T_COMPLEX(ClassInf.RECORD(Absyn.IDENT("SimulationResult")),{
185 DAE.TYPES_VAR("messages",DAE.dummyAttrVar,DAE.T_STRING_DEFAULT,DAE.UNBOUND(),false,NONE()),
186 DAE.TYPES_VAR("flatteningTime",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),false,NONE()),
187 DAE.TYPES_VAR("simulationTime",DAE.dummyAttrVar,DAE.T_REAL_DEFAULT,DAE.UNBOUND(),false,NONE())
188 },NONE(), false);
189
190 //these are in reversed order than above
191 protected constant list<tuple<String,Values.Value>> zeroAdditionalSimulationResultValues =
192 { ("timeTotal", Values.REAL(0.0)),
193 ("timeSimulation", Values.REAL(0.0)),
194 ("timeCompile", Values.REAL(0.0)),
195 ("timeTemplates", Values.REAL(0.0)),
196 ("timeSimCode", Values.REAL(0.0)),
197 ("timeBackend", Values.REAL(0.0)),
198 ("timeFrontend", Values.REAL(0.0))
199 };
200
201 // The build-phase times only (reversed order), for paths that skip translate/
202 // build (resimulateExecutable) but still run the model: createSimulationResult-
203 // FromcallModelExecutable adds the real timeTotal/timeSimulation, and these keep
204 // the result a complete SimulationResult record (0.0 for the phases not run)
205 // instead of a truncated one missing fields.
206 protected constant list<tuple<String,Values.Value>> zeroBuildPhaseResultValues =
207 { ("timeCompile", Values.REAL(0.0)),
208 ("timeTemplates", Values.REAL(0.0)),
209 ("timeSimCode", Values.REAL(0.0)),
210 ("timeBackend", Values.REAL(0.0)),
211 ("timeFrontend", Values.REAL(0.0))
212 };
213
214 protected constant DAE.Exp defaultStartTime = DAE.RCONST(0.0) "default startTime";
215 protected constant DAE.Exp defaultStopTime = DAE.RCONST(1.0) "default stopTime";
216 protected constant DAE.Exp defaultNumberOfIntervals = DAE.ICONST(500) "default numberOfIntervals";
217 protected constant DAE.Exp defaultStepSize = DAE.RCONST(0.002) "default stepSize";
218 protected constant DAE.Exp defaultTolerance = DAE.RCONST(1e-6) "default tolerance";
219 protected constant DAE.Exp defaultMethod = DAE.SCONST("dassl") "default method";
220 protected constant DAE.Exp defaultFileNamePrefix = DAE.SCONST("") "default fileNamePrefix";
221 protected constant DAE.Exp defaultOptions = DAE.SCONST("") "default options";
222 protected constant DAE.Exp defaultOutputFormat = DAE.SCONST("mat") "default outputFormat";
223 protected constant DAE.Exp defaultVariableFilter = DAE.SCONST(".*") "default variableFilter; does whole string matching, i.e. it becomes ^.*$ in the runtime";
224 protected constant DAE.Exp defaultCflags = DAE.SCONST("") "default compiler flags";
225 protected constant DAE.Exp defaultSimflags = DAE.SCONST("") "default simulation flags";
226
227 protected constant InteractiveTypes.SimulationOptions defaultSimulationOptions =
228 InteractiveTypes.SIMULATION_OPTIONS(
229 defaultStartTime,
230 defaultStopTime,
231 defaultNumberOfIntervals,
232 defaultStepSize,
233 defaultTolerance,
234 defaultMethod,
235 defaultFileNamePrefix,
236 defaultOptions,
237 defaultOutputFormat,
238 defaultVariableFilter,
239 defaultCflags,
240 defaultSimflags
241 ) "default simulation options";
242
243 protected constant list<String> simulationOptionsNames =
244 {
245 "startTime",
246 "stopTime",
247 "numberOfIntervals",
248 "tolerance",
249 "method",
250 "fileNamePrefix",
251 "options",
252 "outputFormat",
253 "variableFilter",
254 "cflags",
255 "simflags"
256 } "names of simulation options";
257
258 public function getSimulationResultType
259 output DAE.Type t;
260 algorithm
261
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1211 times.
1211 t := if Testsuite.isRunning() then simulationResultType_rtest else simulationResultType_full;
262 end getSimulationResultType;
263
264 public function getDrModelicaSimulationResultType
265 output DAE.Type t;
266 algorithm
267 ✗ t := if Testsuite.isRunning() then simulationResultType_rtest else simulationResultType_drModelica;
268 end getDrModelicaSimulationResultType;
269
270 public function createSimulationResult
271 input String resultFile;
272 input String options;
273 input String message;
274 input list<tuple<String,Values.Value>> inAddResultValues "additional values in reversed order; expected values see in CevalScript.simulationResultType_full";
275 output Values.Value res;
276 protected
277 list<tuple<String,Values.Value>> resultValues;
278 list<Values.Value> vals;
279 list<String> fields;
280 Boolean notest;
281 algorithm
282 1211 resultValues := listReverse(inAddResultValues);
283 //TODO: maybe we should test if the fields are the ones in simulationResultType_full
284 1211 notest := not Testsuite.isRunning();
285
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1211 times.
1211 fields := if notest then List.map(resultValues, Util.tuple21) else {};
286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1211 times.
1211 vals := if notest then List.map(resultValues, Util.tuple22) else {};
287 2422 res := Values.RECORD(Absyn.IDENT("SimulationResult"),
288 Values.STRING(resultFile)::Values.STRING(options)::Values.STRING(message)::vals,
289 "resultFile"::"simulationOptions"::"messages"::fields,-1);
290 end createSimulationResult;
291
292 public function createSimulationResultFailure
293 input String message;
294 input String options;
295 output Values.Value res;
296 protected
297 algorithm
298 15 res := createSimulationResult("", options, message, zeroAdditionalSimulationResultValues);
299 end createSimulationResultFailure;
300
301 protected function buildCurrentSimulationResultExp
302 output DAE.Exp outExp;
303 protected
304 DAE.ComponentRef cref;
305 algorithm
306 2422 cref := ComponentReferenceBasics.makeCrefIdent("currentSimulationResult",DAE.T_UNKNOWN_DEFAULT,{});
307 2422 outExp := Expression.makeCrefExp(cref,DAE.T_UNKNOWN_DEFAULT);
308 end buildCurrentSimulationResultExp;
309
310 protected function cevalCurrentSimulationResultExp
311 input FCore.Cache inCache;
312 input FCore.Graph env;
313 input String inputFilename;
314 input Absyn.Msg msg;
315 output FCore.Cache outCache;
316 output String filename;
317 algorithm
318 (outCache,filename) := match (inCache, inputFilename)
319 local FCore.Cache cache;
320 case (cache, "<default>")
321 algorithm
322 ✗ (cache,Values.STRING(filename)) := Ceval.ceval(cache,env,buildCurrentSimulationResultExp(),true,msg,0);
323 then (cache,filename);
324 else (inCache,inputFilename);
325 end match;
326 end cevalCurrentSimulationResultExp;
327
328 public function convertSimulationOptionsToSimCode "converts SimulationOptions to SimCode.SimulationSettings"
329 input InteractiveTypes.SimulationOptions opts;
330 output SimCode.SimulationSettings settings;
331 algorithm
332 settings := match opts
333 local
334 Real startTime,stopTime,stepSize,tolerance;
335 Integer nIntervals;
336 String method,format,varFilter,cflags,options,simflags;
337
338 case InteractiveTypes.SIMULATION_OPTIONS(
339 DAE.RCONST(startTime),
340 DAE.RCONST(stopTime),
341 DAE.ICONST(nIntervals),
342 DAE.RCONST(stepSize),
343 DAE.RCONST(tolerance),
344 DAE.SCONST(method),
345 _, /* fileNamePrefix*/
346 _, /* options */
347 DAE.SCONST(format),
348 DAE.SCONST(varFilter),
349 DAE.SCONST(cflags),
350 DAE.SCONST(simflags)) algorithm
351 options := "";
352
353 1353 then SimCode.SIMULATION_SETTINGS(startTime,stopTime,nIntervals,stepSize,tolerance,method,options,format,varFilter,cflags,simflags);
354 end match;
355 end convertSimulationOptionsToSimCode;
356
357 public function buildSimulationOptions
358 "@author: adrpo
359 builds a SimulationOptions record from the given input"
360 input DAE.Exp startTime "start time, default 0.0";
361 input DAE.Exp stopTime "stop time, default 1.0";
362 input DAE.Exp numberOfIntervals "number of intervals, default 500";
363 input DAE.Exp stepSize "stepSize, default (stopTime-startTime)/numberOfIntervals";
364 input DAE.Exp tolerance "tolerance, default 1e-6";
365 input DAE.Exp method "method, default 'dassl'";
366 input DAE.Exp fileNamePrefix "file name prefix, default ''";
367 input DAE.Exp options "options, default ''";
368 input DAE.Exp outputFormat "output format, default 'plt'";
369 input DAE.Exp variableFilter;
370 input DAE.Exp cflags;
371 input DAE.Exp simflags;
372 output InteractiveTypes.SimulationOptions outSimulationOptions;
373 algorithm
374 ✗ outSimulationOptions :=
375 InteractiveTypes.SIMULATION_OPTIONS(
376 startTime,
377 stopTime,
378 numberOfIntervals,
379 stepSize,
380 tolerance,
381 method,
382 fileNamePrefix,
383 options,
384 outputFormat,
385 variableFilter,
386 cflags,
387 simflags
388 );
389 end buildSimulationOptions;
390
391 public function getSimulationOption
392 "@author: adrpo
393 get the value from simulation option"
394 input InteractiveTypes.SimulationOptions inSimOpt;
395 input String optionName;
396 output DAE.Exp outOptionValue;
397 algorithm
398 outOptionValue := match(inSimOpt, optionName)
399 local
400 DAE.Exp e;
401 String name, msg;
402
403 case (InteractiveTypes.SIMULATION_OPTIONS(startTime = e), "startTime") then e;
404 case (InteractiveTypes.SIMULATION_OPTIONS(stopTime = e), "stopTime") then e;
405 case (InteractiveTypes.SIMULATION_OPTIONS(numberOfIntervals = e), "numberOfIntervals") then e;
406 case (InteractiveTypes.SIMULATION_OPTIONS(stepSize = e), "stepSize") then e;
407 case (InteractiveTypes.SIMULATION_OPTIONS(tolerance = e), "tolerance") then e;
408 case (InteractiveTypes.SIMULATION_OPTIONS(method = e), "method") then e;
409 case (InteractiveTypes.SIMULATION_OPTIONS(fileNamePrefix = e), "fileNamePrefix") then e;
410 case (InteractiveTypes.SIMULATION_OPTIONS(options = e), "options") then e;
411 case (InteractiveTypes.SIMULATION_OPTIONS(outputFormat = e), "outputFormat") then e;
412 case (InteractiveTypes.SIMULATION_OPTIONS(variableFilter = e), "variableFilter") then e;
413 case (InteractiveTypes.SIMULATION_OPTIONS(cflags = e), "cflags") then e;
414 case (InteractiveTypes.SIMULATION_OPTIONS(simflags = e), "simflags") then e;
415 case (_, name)
416 algorithm
417 ✗ msg := "Unknown simulation option: " + name;
418 ✗ Error.addCompilerWarning(msg);
419 ✗ then
420 fail();
421 end match;
422 end getSimulationOption;
423
424 public function buildSimulationOptionsFromModelExperimentAnnotation
425 "@author: adrpo
426 retrieve annotation(experiment(....)) values and build a SimulationOptions object to return"
427 input Absyn.Path inModelPath;
428 input String inFileNamePrefix;
429 input Option<InteractiveTypes.SimulationOptions> defaultOption;
430 output InteractiveTypes.SimulationOptions outSimOpt;
431 algorithm
432 outSimOpt := matchcontinue defaultOption
433 local
434 InteractiveTypes.SimulationOptions defaults, simOpt;
435 String experimentAnnotationStr;
436 list<Absyn.NamedArg> named;
437 Option<Absyn.Modification> experiment_ann;
438
439 // search inside annotation(experiment(...))
440 case _
441 algorithm
442 2648 loadProgram(inModelPath);
443 2648 defaults := Util.getOptionOrDefault(defaultOption, setFileNamePrefixInSimulationOptions(defaultSimulationOptions, inFileNamePrefix));
444
445 2648 experiment_ann := InteractiveUtil.getInheritedAnnotation(inModelPath, "experiment", SymbolTable.getAbsyn());
446
447 // TODO: Get the values from the modifier directly instead of this mess.
448 2647 experimentAnnotationStr := Interactive.getExperimentAnnotationString(experiment_ann);
449
450 // parse the string we get back, either {} or {StopTime=5, Tolerance = 0.10};
451 // jump to next case if the annotation is empty
452
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 449 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
449 false := stringEq(experimentAnnotationStr, "{}");
453
454 // get rid of '{' and '}'
455 449 experimentAnnotationStr := System.stringReplace(experimentAnnotationStr, "{", "");
456 449 experimentAnnotationStr := System.stringReplace(experimentAnnotationStr, "}", "");
457
458
5/10
✗ Branch 3 not taken.
✓ Branch 4 taken 449 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 449 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 449 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 449 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 449 times.
449 GlobalScript.ISTMTS({GlobalScript.IEXP(exp = Absyn.CALL(functionArgs = Absyn.FUNCTIONARGS(_, named)))}, _)
459 := Parser.parsestringexp("experiment(" + experimentAnnotationStr + ");\n", "<experiment>");
460
461 449 simOpt := populateSimulationOptions(defaults, named);
462 then
463 simOpt;
464
465 // if we fail, just use the defaults
466 else
467 algorithm
468 2199 defaults := setFileNamePrefixInSimulationOptions(defaultSimulationOptions, inFileNamePrefix);
469 then defaults;
470 end matchcontinue;
471 end buildSimulationOptionsFromModelExperimentAnnotation;
472
473 protected function setFileNamePrefixInSimulationOptions
474 input InteractiveTypes.SimulationOptions inSimOpt;
475 input String inFileNamePrefix;
476 output InteractiveTypes.SimulationOptions outSimOpt;
477 protected
478 DAE.Exp startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, options, outputFormat, variableFilter, cflags, simflags;
479 Boolean UseOtimica;
480 algorithm
481
4/4
✓ Branch 1 taken 4805 times.
✓ Branch 2 taken 42 times.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 4781 times.
4847 UseOtimica := Config.acceptOptimicaGrammar() or Flags.getConfigBool(Flags.GENERATE_DYN_OPTIMIZATION_PROBLEM);
482 4847 InteractiveTypes.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, _, options, outputFormat, variableFilter, cflags, simflags) := inSimOpt;
483
2/2
✓ Branch 0 taken 4781 times.
✓ Branch 1 taken 66 times.
4847 if UseOtimica then
484 method := DAE.SCONST("optimization");
485 elseif Flags.getConfigBool(Flags.DAE_MODE) then
486 method := DAE.SCONST("ida");
487 end if;
488
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 4781 times.
4847 numberOfIntervals := if UseOtimica then DAE.ICONST(50) else numberOfIntervals;
489 4847 outSimOpt := InteractiveTypes.SIMULATION_OPTIONS(startTime, stopTime, numberOfIntervals, stepSize, tolerance, method, DAE.SCONST(inFileNamePrefix), options, outputFormat, variableFilter, cflags, simflags);
490 end setFileNamePrefixInSimulationOptions;
491
492 protected function getConst
493 "@author: adrpo
494 Tranform a literal Absyn.Exp to DAE.Exp with the given DAE.Type"
495 input Absyn.Exp inAbsynExp;
496 input DAE.Type inExpType;
497 output DAE.Exp outExp;
498 algorithm
499 outExp := matchcontinue(inAbsynExp, inExpType)
500 local
501 Integer i;
502 Real r;
503 Absyn.Exp exp;
504 String str;
505
506 case (Absyn.UNARY(Absyn.UMINUS(),exp), _)
507 algorithm
508
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 DAE.ICONST(i) := getConst(exp, inExpType);
509 ✗ i := intNeg(i);
510 ✗ then
511 DAE.ICONST(i);
512
513 case (Absyn.UNARY(Absyn.UMINUS(),exp), _)
514 algorithm
515
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 DAE.RCONST(r) := getConst(exp, inExpType);
516 2 r := realNeg(r);
517 2 then
518 DAE.RCONST(r);
519
520 49 case (Absyn.INTEGER(i), DAE.T_INTEGER()) then DAE.ICONST(i);
521 328 case (Absyn.REAL(str), DAE.T_REAL()) algorithm r := stringReal(str); then DAE.RCONST(r);
522 397 case (Absyn.INTEGER(i), DAE.T_REAL()) algorithm r := intReal(i); then DAE.RCONST(r);
523
524 else
525 algorithm
526 ✗ str := "CevalScript.getConst: experiment annotation contains unsupported expression: " + Dump.printExpStr(inAbsynExp) + " of type " + TypesDump.unparseType(inExpType) + "\n";
527 ✗ Error.addCompilerError(str);
528 ✗ then
529 fail();
530 end matchcontinue;
531 end getConst;
532
533 protected function populateSimulationOptions
534 input output InteractiveTypes.SimulationOptions options;
535 input list<Absyn.NamedArg> args;
536 protected
537 String name;
538 Absyn.Exp value;
539 Option<DAE.Exp> interval = NONE();
540 algorithm
541
2/2
✓ Branch 0 taken 781 times.
✓ Branch 1 taken 449 times.
1230 for arg in args loop
542 781 Absyn.NAMEDARG(argName = name, argValue = value) := arg;
543
544 () := match name
545 95 case "Tolerance" algorithm options.tolerance := getConst(value, DAE.T_REAL_DEFAULT); then ();
546 88 case "StartTime" algorithm options.startTime := getConst(value, DAE.T_REAL_DEFAULT); then ();
547 448 case "StopTime" algorithm options.stopTime := getConst(value, DAE.T_REAL_DEFAULT); then ();
548 49 case "NumberOfIntervals" algorithm options.numberOfIntervals := getConst(value, DAE.T_INTEGER_DEFAULT); then ();
549 92 case "Interval" algorithm interval := SOME(getConst(value, DAE.T_REAL_DEFAULT)); then ();
550 else
551 algorithm
552
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 6 times.
9 if not StringUtil.startsWith(name, "__") then
553 3 Error.addCompilerWarning("Ignoring unknown experiment annotation option: " +
554 name + " = " + Dump.printExpStr(value));
555 end if;
556 then
557 ();
558 end match;
559 end for;
560
561 // Interval needs to be handled last since it depends on the start and stop time.
562
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 449 times.
✓ Branch 2 taken 357 times.
✓ Branch 3 taken 92 times.
449 if isSome(interval) then
563 92 options := setSimulationOptionsInterval(options, Expression.toReal(Util.getOption(interval)));
564 else
565 /*fix issue 12070, set proper default value of stepSize when Interval annotation is not provided
566 stepSize = (StopTime-StartTime)/500
567 */
568 714 options.stepSize := DAE.RCONST((Expression.toReal(options.stopTime) - Expression.toReal(options.startTime)) / 500);
569 end if;
570 end populateSimulationOptions;
571
572 function setSimulationOptionsInterval
573 input output InteractiveTypes.SimulationOptions options;
574 input Real interval;
575 protected
576 Real start_time, stop_time;
577 algorithm
578 92 start_time := Expression.toReal(options.startTime);
579 92 stop_time := Expression.toReal(options.stopTime);
580
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 92 times.
92 options.stepSize := DAE.RCONST(interval);
581 // Round to nearest integer
582 options.numberOfIntervals := DAE.ICONST(realInt((stop_time - start_time) / interval + 0.5));
583 end setSimulationOptionsInterval;
584
585 protected function simOptionsAsString
586 "@author: adrpo
587 Gets the simulation options as string"
588 input list<Values.Value> vals;
589 output String str;
590 algorithm
591 str := matchcontinue vals
592 local
593 list<String> simOptsValues;
594 list<Values.Value> lst;
595
596 case _::lst
597 algorithm
598 // build a list with the values
599 1211 simOptsValues := List.map(lst, ValuesDump.valString);
600 // trim " from strings!
601 1211 simOptsValues := List.map2(simOptsValues, System.stringReplace, "\"", "\'");
602
603 1211 str := Util.buildMapStr(simulationOptionsNames, simOptsValues, " = ", ", ");
604 then
605 str;
606
607 // on failure
608 case _::lst
609 algorithm
610 // build a list with the values
611 ✗ simOptsValues := List.map(lst, ValuesDump.valString);
612 // trim " from strings!
613 ✗ simOptsValues := List.map2(simOptsValues, System.stringReplace, "\"", "\'");
614
615 ✗ str := stringDelimitList(simOptsValues, ", ");
616 then
617 str;
618 end matchcontinue;
619 end simOptionsAsString;
620
621 protected function diffSanityCheckEqual
622 "Sanity check for the Modelica source diff/merge: returns true when s1 and
623 s2 represent the same Modelica program. Code tokens are compared strictly
624 (ignoring whitespace), while comments are compared as a multiset so the
625 merge step is free to relocate them."
626 input String s1;
627 input String s2;
628 output Boolean b;
629 protected
630 import LexerModelicaDiff.{Token,tokenContent,scanString,isLineComment,isBlockComment,blockCommentCanonical,modelicaDiffTokenWhitespace};
631 list<Token> ts1, ts2;
632 list<String> comments1, comments2;
633 algorithm
634 46 (ts1, _) := scanString(s1);
635 46 (ts2, _) := scanString(s2);
636
14/16
✓ Branch 1 taken 746 times.
✓ Branch 2 taken 1083 times.
✓ Branch 3 taken 1829 times.
✓ Branch 4 taken 46 times.
✓ Branch 5 taken 1083 times.
✓ Branch 6 taken 46 times.
✓ Branch 9 taken 746 times.
✓ Branch 10 taken 1083 times.
✓ Branch 11 taken 1829 times.
✓ Branch 12 taken 46 times.
✓ Branch 13 taken 1083 times.
✓ Branch 14 taken 46 times.
✓ Branch 18 taken 46 times.
✗ Branch 19 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 46 times.
3704 if stringAppendList(list(tokenContent(t) for t guard not modelicaDiffTokenWhitespace(t) in ts1)) <>
637 stringAppendList(list(tokenContent(t) for t guard not modelicaDiffTokenWhitespace(t) in ts2)) then
638 b := false;
639 ✗ return;
640 end if;
641
8/8
✓ Branch 1 taken 1821 times.
✓ Branch 2 taken 8 times.
✓ Branch 4 taken 1809 times.
✓ Branch 5 taken 12 times.
✓ Branch 6 taken 1829 times.
✓ Branch 7 taken 46 times.
✓ Branch 8 taken 20 times.
✓ Branch 9 taken 46 times.
1875 comments1 := List.sort(list(diffSanityCheckCommentStr(t)
642 for t guard isLineComment(t) or isBlockComment(t) in ts1),
643 Util.strcmpBool);
644
8/8
✓ Branch 1 taken 1821 times.
✓ Branch 2 taken 8 times.
✓ Branch 4 taken 1809 times.
✓ Branch 5 taken 12 times.
✓ Branch 6 taken 1829 times.
✓ Branch 7 taken 46 times.
✓ Branch 8 taken 20 times.
✓ Branch 9 taken 46 times.
1875 comments2 := List.sort(list(diffSanityCheckCommentStr(t)
645 for t guard isLineComment(t) or isBlockComment(t) in ts2),
646 Util.strcmpBool);
647 46 b := List.isEqualOnTrue(comments1, comments2, stringEq);
648 end diffSanityCheckEqual;
649
650 protected function diffSanityCheckCommentStr
651 "Canonical string form of a comment token. Block comments are normalised by
652 trimming each line, so that re-indented block comments compare equal."
653 input LexerModelicaDiff.Token t;
654 output String s;
655 protected
656 import LexerModelicaDiff.{tokenContent,isBlockComment,blockCommentCanonical};
657 algorithm
658
2/2
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 16 times.
40 s := if isBlockComment(t) then stringDelimitList(blockCommentCanonical(t), "\n")
659 else tokenContent(t);
660 end diffSanityCheckCommentStr;
661
662 public function cevalInteractiveFunctions3
663 "defined in the interactive environment."
664 input FCore.Cache inCache;
665 input FCore.Graph inEnv;
666 input String inFunctionName;
667 input list<Values.Value> inVals;
668 input Absyn.Msg msg;
669 output FCore.Cache outCache = inCache;
670 output Values.Value outValue;
671 protected
672 import LexerModelicaDiff.{Token,TokenId,tokenContent,scanString,reportErrors,filterModelicaDiff,modelicaDiffTokenEq,modelicaDiffTokenWhitespace};
673 import DiffAlgorithm.{Diff,diff,printActual,printDiffTerminalColor,printDiffXml};
674 algorithm
675 outValue := matchcontinue (inFunctionName,inVals)
676 local
677 String simflags,s1,s2,s3,s4,s5,str,str1,str2,str3,str4,executable,
678 outputFormat_str,initfilename,pd,executableSuffixedExe,sim_call,result_file,filename_1,filename,
679 name,errMsg, res,workdir,filenameprefix,compileDir,exeDir, logFile, outputFile,
680 strlinearizeTime, modeldescriptionfilename, tmpDir, tmpFile, bom, description, resimulateExecutable;
681 list<Values.Value> vals;
682 Absyn.Path path,classpath,className;
683 SCode.Program sp;
684 FCore.Graph env;
685 Absyn.Program p,pnew;
686 Absyn.Class absynClass;
687 Absyn.Element elem;
688 Absyn.Exp aexp;
689 DAE.DAElist dae;
690 BackendDAE.BackendDAE daelow;
691 BackendDAE.Variables vars;
692 BackendDAE.EquationArray eqnarr;
693 array<list<Integer>> m;
694 Option<list<tuple<Integer, Integer, BackendDAE.Equation>>> jac;
695 Values.Value ret_val,simValue,v,v1,v2;
696 SimCode.SimulationSettings simSettings;
697 Integer i,i1,resI;
698 Option<Integer> fmiContext, fmiInstance, fmiModelVariablesInstance; /* void* implementation: DO NOT UNBOX THE POINTER AS THAT MIGHT CHANGE IT. Just treat this as an opaque type. */
699 Integer fmiLogLevel, direction;
700 list<Integer> is;
701 list<FMI.TypeDefinitions> fmiTypeDefinitionsList;
702 list<FMI.ModelVariables> fmiModelVariablesList;
703 FMI.ExperimentAnnotation fmiExperimentAnnotation;
704 FMI.Info fmiInfo;
705 list<String> strs,strs1,strs2;
706 Real timeTotal,timeSimulation,linearizeTime,offset,offset1,offset2,scaleFactor,scaleFactor1,scaleFactor2;
707 Boolean bval, b, b1, b2, b3, b4, b5, showProtected, inputConnectors, outputConnectors, sanityCheckFailed, lineEndingIsCRLF;
708 list<tuple<String,Values.Value>> resultValues;
709 list<Values.Value> cvars;
710 list<Absyn.Path> paths;
711 list<Absyn.Class> classes;
712 list<Absyn.ElementArg> eltargs;
713 Absyn.Within within_;
714 BackendDAE.EqSystem syst;
715 BackendDAE.Shared shared;
716 Boolean dumpExtractionSteps;
717 list<Boolean> blst;
718 UnitAbsyn.Unit u1,u2;
719 list<Token> tokens1, tokens2, errorTokens;
720 list<SimpleModelicaParser.ParseTree> parseTree1, parseTree2;
721 //list<tuple<Diff, list<Token>>> diffs;
722 list<tuple<Diff, list<SimpleModelicaParser.ParseTree>>> treeDiffs;
723 SymbolTable forkedSymbolTable;
724 SimCode.SimulationSettings simSettings;
725
726 case ("runScriptParallel",{Values.ARRAY(valueLst=vals),Values.INTEGER(i),Values.BOOL(true)})
727 algorithm
728 ✗ strs := List.map(vals,ValuesUtil.extractValueString);
729 /* One of the few times we can allow to directly manipulate the symbol table
730 * Each thread will get a copy of the symbol table and the results will not
731 * be stored in the parent.
732 */
733 ✗ forkedSymbolTable := SymbolTable.get();
734 ✗ blst := System.launchParallelTasks(i, List.map1(strs, Util.makeTuple, forkedSymbolTable), Interactive.evaluateFork);
735 ✗ v := ValuesMake.makeArray(List.map(blst, ValuesMake.makeBoolean));
736 ✗ SymbolTable.update(forkedSymbolTable);
737 then
738 v;
739
740 case ("runScriptParallel",{Values.ARRAY(valueLst=vals),Values.INTEGER(i),Values.BOOL(false)})
741 algorithm
742 ✗ strs := List.map(vals,ValuesUtil.extractValueString);
743 ✗ strs := List.map1r(strs, stringAppend, stringAppend(Settings.getInstallationDirectoryPath(),"/bin/omc "));
744 ✗ is := System.systemCallParallel(strs,i);
745 ✗ then
746 ValuesMake.makeArray(List.map(List.map1(is,intEq,0), ValuesMake.makeBoolean));
747
748 case ("runScriptParallel",{Values.ARRAY(valueLst=vals),_,_})
749 ✗ then ValuesMake.makeArray(List.fill(Values.BOOL(false), listLength(vals)));
750
751 case ("setClassComment",{Values.CODE(Absyn.C_TYPENAME(path)),Values.STRING(str)})
752 algorithm
753 2 (p,b) := Interactive.setClassComment(path, str, SymbolTable.getAbsyn());
754 2 SymbolTable.setAbsyn(p);
755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 then
756 Values.BOOL(b);
757
758 case ("isShortDefinition", {Values.CODE(Absyn.C_TYPENAME(path))})
759 algorithm
760 ✗ b := isShortDefinition(path, SymbolTable.getAbsyn());
761 ✗ then
762 Values.BOOL(b);
763
764 case ("getUsedClassNames",{Values.CODE(Absyn.C_TYPENAME(path))})
765 algorithm
766 ✗ sp := SymbolTable.getSCode();
767 ✗ (sp, _) := NFSCodeFlatten.flattenClassInProgram(path, sp);
768 ✗ sp := SCodeUtil.removeBuiltinsFromTopScope(sp);
769 ✗ paths := Interactive.getSCodeClassNamesRecursive(sp);
770 // paths = bcallret2(sort, List.sort, paths, AbsynUtil.pathGe, paths);
771 ✗ then
772 ValuesMake.makeCodeTypeNameArray(paths);
773
774 case ("getUsedClassNames",_)
775 ✗ then ValuesMake.makeArray({});
776
777 case ("getClassComment",{Values.CODE(Absyn.C_TYPENAME(path))})
778 algorithm
779 ✗ elem := InteractiveUtil.getPathedElementInProgram(path, SymbolTable.getAbsyn());
780 ✗ str := System.unescapedString(getClassElementComment(elem));
781 ✗ then
782 Values.STRING(str);
783
784 case ("getClassComment",{Values.CODE(Absyn.C_TYPENAME(_))})
785 then
786 Values.STRING("");
787
788 case ("getPackages",{Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT("AllLoadedClasses")))})
789 algorithm
790 ✗ paths := Interactive.getTopPackages(SymbolTable.getAbsyn());
791 ✗ then
792 ValuesMake.makeCodeTypeNameArray(paths);
793
794 case ("getPackages",{Values.CODE(Absyn.C_TYPENAME(path))})
795 algorithm
796 ✗ paths := Interactive.getPackagesInPath(path, SymbolTable.getAbsyn());
797 ✗ then
798 ValuesMake.makeCodeTypeNameArray(paths);
799
800 case ("convertUnits",{Values.STRING(str1),Values.STRING(str2)})
801 algorithm
802 14 Error.clearMessages() "Clear messages";
803 14 UnitParserExt.initSIUnits();
804 14 (u1,scaleFactor1,offset1) := UnitAbsynBuilder.str2unitWithScaleFactor(str1,NONE());
805 14 (u2,scaleFactor2,offset2) := UnitAbsynBuilder.str2unitWithScaleFactor(str2,NONE());
806 13 b := valueEq(u1,u2);
807 /* How to calculate the final scale factor and offset:
808 F = C*1.8 + 32
809 C = (F - 32)/1.8 = F/1.8 - 32/1.8
810 */
811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 scaleFactor := realDiv(scaleFactor2, scaleFactor1);
812 13 offset := realDiv(realSub(offset2, offset1), scaleFactor1);
813
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 12 times.
27 then
814 Values.TUPLE({Values.BOOL(b),Values.REAL(scaleFactor),Values.REAL(offset)});
815
816 case ("convertUnits",{Values.STRING(_),Values.STRING(_)})
817 then Values.TUPLE({Values.BOOL(false),Values.REAL(1.0),Values.REAL(0.0)});
818
819 case ("getDerivedUnits",{Values.STRING(str1)})
820 algorithm
821 4 Error.clearMessages() "Clear messages";
822 4 UnitParserExt.initSIUnits();
823 4 u1 := UnitAbsynBuilder.str2unit(str1, NONE());
824 3 strs := UnitAbsynBuilder.getDerivedUnits(u1, str1);
825 3 then
826 ValuesMake.makeArray(List.map(strs, ValuesMake.makeString));
827
828 case ("getDerivedUnits",{Values.STRING(_)})
829 1 then ValuesMake.makeArray({});
830
831 case ("getClassInformation",{Values.CODE(Absyn.C_TYPENAME(className))})
832 6 then getClassInformation(className, SymbolTable.getAbsyn());
833
834 case ("getClassInformation",_)
835 then Values.TUPLE({Values.STRING(""),Values.STRING(""),Values.BOOL(false),Values.BOOL(false),Values.BOOL(false),Values.STRING(""),
836 Values.BOOL(false),Values.INTEGER(0),Values.INTEGER(0),Values.INTEGER(0),Values.INTEGER(0),Values.ARRAY({},{0}),
837 Values.BOOL(false),Values.BOOL(false),Values.STRING(""),Values.STRING(""),Values.BOOL(false),Values.STRING("")});
838
839 case ("getTransitions",{Values.CODE(Absyn.C_TYPENAME(className))})
840 algorithm
841
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 false := Interactive.existClass(className, SymbolTable.getAbsyn());
842 ✗ str := AbsynUtil.pathString(className);
843 ✗ Error.addMessage(Error.LOOKUP_ERROR, {str,"<TOP>"});
844 ✗ then ValuesMake.makeArray({});
845
846 case ("getTransitions",{Values.CODE(Absyn.C_TYPENAME(className))})
847 4 then getTransitions(className, SymbolTable.getAbsyn());
848
849 case ("getTransitions",_)
850 ✗ then ValuesMake.makeArray({});
851
852 case ("addTransition",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(_), Values.STRING(_), Values.STRING(_),
853 Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.INTEGER(_), Values.CODE(Absyn.C_EXPRESSION(_))})
854 algorithm
855
1/2
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 false := Interactive.existClass(classpath, SymbolTable.getAbsyn());
856 ✗ str := AbsynUtil.pathString(classpath);
857 ✗ Error.addMessage(Error.LOOKUP_ERROR, {str,"<TOP>"});
858 then
859 Values.BOOL(false);
860
861 case ("addTransition",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(_), Values.STRING(_), Values.STRING(_),
862 Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.INTEGER(_),
863 Values.CODE(Absyn.C_MODIFICATION(Absyn.CLASSMOD(eqMod=Absyn.NOMOD())))})
864 algorithm
865 ✗ false := Interactive.existClass(classpath, SymbolTable.getAbsyn());
866 ✗ str := AbsynUtil.pathString(classpath);
867 ✗ Error.addMessage(Error.LOOKUP_ERROR, {str,"<TOP>"});
868 then
869 Values.BOOL(false);
870
871 case ("addTransition",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(str1), Values.STRING(str2), Values.STRING(str3),
872 Values.BOOL(b), Values.BOOL(b1), Values.BOOL(b2), Values.INTEGER(i), Values.CODE(Absyn.C_EXPRESSION(aexp))})
873 algorithm
874 2 (bval, p) := Interactive.addTransition(AbsynUtil.pathToCref(classpath), str1, str2, str3, b, b1, b2, i, Absyn.NAMEDARG("annotate",aexp)::{}, SymbolTable.getAbsyn());
875 1 SymbolTable.setAbsyn(p);
876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
877 Values.BOOL(bval);
878
879 case ("addTransition",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(str1), Values.STRING(str2), Values.STRING(str3),
880 Values.BOOL(b), Values.BOOL(b1), Values.BOOL(b2), Values.INTEGER(i),
881 Values.CODE(Absyn.C_MODIFICATION(Absyn.CLASSMOD(elementArgLst=eltargs,eqMod=Absyn.NOMOD())))})
882 algorithm
883 ✗ (bval, p) := Interactive.addTransitionWithAnnotation(AbsynUtil.pathToCref(classpath), str1, str2, str3, b, b1, b2, i, Absyn.ANNOTATION(eltargs), SymbolTable.getAbsyn());
884 ✗ SymbolTable.setAbsyn(p);
885 ✗ then
886 Values.BOOL(bval);
887
888 case ("addTransition",{_,_,_,_,_,_,_,_,_})
889 then Values.BOOL(false);
890
891 case ("deleteTransition",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(_), Values.STRING(_), Values.STRING(_),
892 Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.INTEGER(_)})
893 algorithm
894
1/2
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 false := Interactive.existClass(classpath, SymbolTable.getAbsyn());
895 ✗ str := AbsynUtil.pathString(classpath);
896 ✗ Error.addMessage(Error.LOOKUP_ERROR, {str,"<TOP>"});
897 then
898 Values.BOOL(false);
899
900 case ("deleteTransition",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(str1), Values.STRING(str2), Values.STRING(str3),
901 Values.BOOL(b), Values.BOOL(b1), Values.BOOL(b2), Values.INTEGER(i)})
902 algorithm
903 1 (bval, p) := Interactive.deleteTransition(AbsynUtil.pathToCref(classpath), str1, str2, str3, b, b1, b2, i, SymbolTable.getAbsyn());
904 1 SymbolTable.setAbsyn(p);
905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
906 Values.BOOL(bval);
907
908 case ("deleteTransition",{_,_,_,_,_,_,_,_})
909 then
910 Values.BOOL(false);
911
912 case ("updateTransition",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(_), Values.STRING(_), Values.STRING(_),
913 Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.INTEGER(_), Values.STRING(_),
914 Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.INTEGER(_), Values.CODE(Absyn.C_EXPRESSION(_))})
915 algorithm
916
1/2
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 false := Interactive.existClass(classpath, SymbolTable.getAbsyn());
917 ✗ str := AbsynUtil.pathString(classpath);
918 ✗ Error.addMessage(Error.LOOKUP_ERROR, {str,"<TOP>"});
919 then
920 Values.BOOL(false);
921
922 case ("updateTransition",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(_), Values.STRING(_), Values.STRING(_),
923 Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.INTEGER(_), Values.STRING(_),
924 Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.INTEGER(_),
925 Values.CODE(Absyn.C_MODIFICATION(Absyn.CLASSMOD(eqMod=Absyn.NOMOD())))})
926 algorithm
927 ✗ false := Interactive.existClass(classpath, SymbolTable.getAbsyn());
928 ✗ str := AbsynUtil.pathString(classpath);
929 ✗ Error.addMessage(Error.LOOKUP_ERROR, {str,"<TOP>"});
930 then
931 Values.BOOL(false);
932
933 case ("updateTransition",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(str1), Values.STRING(str2), Values.STRING(str3),
934 Values.BOOL(b), Values.BOOL(b1), Values.BOOL(b2), Values.INTEGER(i), Values.STRING(str4),
935 Values.BOOL(b3), Values.BOOL(b4), Values.BOOL(b5), Values.INTEGER(i1), Values.CODE(Absyn.C_EXPRESSION(aexp))})
936 algorithm
937 1 (bval, p) := Interactive.deleteTransition(AbsynUtil.pathToCref(classpath), str1, str2, str3, b, b1, b2, i, SymbolTable.getAbsyn());
938 2 (bval, p) := Interactive.addTransition(AbsynUtil.pathToCref(classpath), str1, str2, str4, b3, b4, b5, i1, Absyn.NAMEDARG("annotate",aexp)::{}, p);
939 1 SymbolTable.setAbsyn(p);
940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
941 Values.BOOL(bval);
942
943 case ("updateTransition",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(str1), Values.STRING(str2), Values.STRING(str3),
944 Values.BOOL(b), Values.BOOL(b1), Values.BOOL(b2), Values.INTEGER(i), Values.STRING(str4),
945 Values.BOOL(b3), Values.BOOL(b4), Values.BOOL(b5), Values.INTEGER(i1),
946 Values.CODE(Absyn.C_MODIFICATION(Absyn.CLASSMOD(elementArgLst=eltargs,eqMod=Absyn.NOMOD())))})
947 algorithm
948 ✗ (bval, p) := Interactive.deleteTransition(AbsynUtil.pathToCref(classpath), str1, str2, str3, b, b1, b2, i, SymbolTable.getAbsyn());
949 ✗ (bval, p) := Interactive.addTransitionWithAnnotation(AbsynUtil.pathToCref(classpath), str1, str2, str4, b3, b4, b5, i1, Absyn.ANNOTATION(eltargs), p);
950 ✗ SymbolTable.setAbsyn(p);
951 ✗ then
952 Values.BOOL(bval);
953
954 case ("updateTransition",_)
955 then
956 Values.BOOL(false);
957
958 case ("getInitialStates",{Values.CODE(Absyn.C_TYPENAME(className))})
959 algorithm
960
1/2
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 false := Interactive.existClass(className, SymbolTable.getAbsyn());
961 ✗ str := AbsynUtil.pathString(className);
962 ✗ Error.addMessage(Error.LOOKUP_ERROR, {str,"<TOP>"});
963 ✗ then
964 ValuesMake.makeArray({});
965
966 case ("getInitialStates",{Values.CODE(Absyn.C_TYPENAME(className))})
967 1 then getInitialStates(className, SymbolTable.getAbsyn());
968
969 case ("getInitialStates",_)
970 ✗ then ValuesMake.makeArray({});
971
972 case ("addInitialState",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(_), Values.CODE(Absyn.C_EXPRESSION(_))})
973 algorithm
974
1/2
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 false := Interactive.existClass(classpath, SymbolTable.getAbsyn());
975 ✗ str := AbsynUtil.pathString(classpath);
976 ✗ Error.addMessage(Error.LOOKUP_ERROR, {str,"<TOP>"});
977 then
978 Values.BOOL(false);
979
980 case ("addInitialState",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(_),
981 Values.CODE(Absyn.C_MODIFICATION(Absyn.CLASSMOD(eqMod=Absyn.NOMOD())))})
982 algorithm
983 ✗ false := Interactive.existClass(classpath, SymbolTable.getAbsyn());
984 ✗ str := AbsynUtil.pathString(classpath);
985 ✗ Error.addMessage(Error.LOOKUP_ERROR, {str,"<TOP>"});
986 then
987 Values.BOOL(false);
988
989 case ("addInitialState",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(str1), Values.CODE(Absyn.C_EXPRESSION(aexp))})
990 algorithm
991 2 (bval, p) := addInitialState(classpath, str1, Absyn.NAMEDARG("annotate",aexp)::{}, SymbolTable.getAbsyn());
992 1 SymbolTable.setAbsyn(p);
993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
994 Values.BOOL(bval);
995
996 case ("addInitialState",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(str1),
997 Values.CODE(Absyn.C_MODIFICATION(Absyn.CLASSMOD(elementArgLst=eltargs,eqMod=Absyn.NOMOD())))})
998 algorithm
999 ✗ (bval, p) := addInitialStateWithAnnotation(classpath, str1, Absyn.ANNOTATION(eltargs), SymbolTable.getAbsyn());
1000 ✗ SymbolTable.setAbsyn(p);
1001 ✗ then
1002 Values.BOOL(bval);
1003
1004 case ("deleteInitialState",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(_)})
1005 algorithm
1006
1/2
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 false := Interactive.existClass(classpath, SymbolTable.getAbsyn());
1007 ✗ str := AbsynUtil.pathString(classpath);
1008 ✗ Error.addMessage(Error.LOOKUP_ERROR, {str,"<TOP>"});
1009 then
1010 Values.BOOL(false);
1011
1012 case ("deleteInitialState",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(str1)})
1013 algorithm
1014 1 (bval, p) := deleteInitialState(classpath, str1, SymbolTable.getAbsyn());
1015 1 SymbolTable.setAbsyn(p);
1016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
1017 Values.BOOL(bval);
1018
1019 case ("deleteInitialState",_)
1020 then
1021 Values.BOOL(false);
1022
1023 case ("updateInitialState",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(_), Values.CODE(Absyn.C_EXPRESSION(_))})
1024 algorithm
1025
1/2
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 false := Interactive.existClass(classpath, SymbolTable.getAbsyn());
1026 ✗ str := AbsynUtil.pathString(classpath);
1027 ✗ Error.addMessage(Error.LOOKUP_ERROR, {str,"<TOP>"});
1028 then
1029 Values.BOOL(false);
1030
1031 case ("updateInitialState",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(_),
1032 Values.CODE(Absyn.C_MODIFICATION(Absyn.CLASSMOD(eqMod=Absyn.NOMOD())))})
1033 algorithm
1034 ✗ false := Interactive.existClass(classpath, SymbolTable.getAbsyn());
1035 ✗ str := AbsynUtil.pathString(classpath);
1036 ✗ Error.addMessage(Error.LOOKUP_ERROR, {str,"<TOP>"});
1037 then
1038 Values.BOOL(false);
1039
1040 case ("updateInitialState",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(str1), Values.CODE(Absyn.C_EXPRESSION(aexp))})
1041 algorithm
1042 1 (bval, p) := deleteInitialState(classpath, str1, SymbolTable.getAbsyn());
1043 2 (bval, p) := addInitialState(classpath, str1, Absyn.NAMEDARG("annotate",aexp)::{}, p);
1044 1 SymbolTable.setAbsyn(p);
1045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
1046 Values.BOOL(bval);
1047
1048 case ("updateInitialState",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(str1),
1049 Values.CODE(Absyn.C_MODIFICATION(Absyn.CLASSMOD(elementArgLst=eltargs,eqMod=Absyn.NOMOD())))})
1050 algorithm
1051 ✗ (bval, p) := deleteInitialState(classpath, str1, SymbolTable.getAbsyn());
1052 ✗ (bval, p) := addInitialStateWithAnnotation(classpath, str1, Absyn.ANNOTATION(eltargs), p);
1053 ✗ SymbolTable.setAbsyn(p);
1054 ✗ then
1055 Values.BOOL(bval);
1056
1057 case ("updateInitialState",_)
1058 then Values.BOOL(false);
1059
1060 case ("diffModelicaFileListings",{Values.STRING(s1),Values.STRING(s2),Values.ENUM_LITERAL(name=path),Values.BOOL(b)})
1061 algorithm
1062 46 ExecStat.execStatReset();
1063
1064 46 (s1, bom) := StringUtil.stripBOM(s1);
1065 // Work internally with LF line endings only, so that lines coming from
1066 // the original file (s1) and lines produced by the listing (s2, always LF)
1067 // compare and merge uniformly. Remember the original (s1) convention and
1068 // restore it on output, so we do not rewrite every line ending of a file
1069 // that uses CRLF (e.g. on Windows checkouts). See #13447.
1070
2/4
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 46 times.
46 lineEndingIsCRLF := s1 <> System.stringReplace(s1, "\r\n", "\n"); // removing CRLF changed s1 => it originally contained CRLF
1071 46 s1 := System.stringReplace(s1, "\r\n", "\n");
1072 46 s1 := System.stringReplace(s1, "\r", "\n"); // also fold any remaining lone CR (old Mac) to LF
1073 46 (tokens1, errorTokens) := scanString(s1);
1074 46 reportErrors(errorTokens);
1075
1076 if false and s1<>stringAppendList(list(tokenContent(t) for t in tokens1)) then
1077 // Debugging code. Make sure the scanner works before debugging the diff.
1078 System.writeFile("string.before", s1);
1079 System.writeFile("string.after", stringAppendList(list(tokenContent(t) for t in tokens1)));
1080 Error.terminate("Lexed string does not match the original. See files string.before and string.after", sourceInfo());
1081 fail();
1082 end if;
1083
1084 46 ExecStat.execStat("diffModelicaFileListings scan string 1");
1085 46 (_,parseTree1) := SimpleModelicaParser.stored_definition(tokens1, {});
1086 46 ExecStat.execStat("diffModelicaFileListings parse string 1");
1087
1088 if false and s1<>SimpleModelicaParser.parseTreeStr(parseTree1) then
1089 // Debugging code. Make sure the parser works before debugging the diff.
1090 System.writeFile("string.before", s1);
1091 System.writeFile("string.after", SimpleModelicaParser.parseTreeStr(parseTree1));
1092 Error.terminate("Parsed string does not match the original. See files string.before and string.after", sourceInfo());
1093 fail();
1094 end if;
1095
1096 46 (s2, bom) := StringUtil.stripBOM(s2);
1097 46 s2 := System.stringReplace(s2, "\r\n", "\n");
1098 46 s2 := System.stringReplace(s2, "\r", "\n");
1099 46 (tokens2, errorTokens) := scanString(s2);
1100 46 reportErrors(errorTokens);
1101 46 ExecStat.execStat("diffModelicaFileListings scan string 2");
1102 46 (_,parseTree2) := SimpleModelicaParser.stored_definition(tokens2, {});
1103 46 ExecStat.execStat("diffModelicaFileListings parse string 2");
1104
1105 if false and s2<>SimpleModelicaParser.parseTreeStr(parseTree2) then
1106 // Debugging code. Make sure the parser works before debugging the diff.
1107 System.writeFile("string.before", s2);
1108 System.writeFile("string.after", SimpleModelicaParser.parseTreeStr(parseTree2));
1109 Error.terminate("Parsed string does not match the original. See files string.before and string.after", sourceInfo());
1110 fail();
1111 end if;
1112
1113 46 treeDiffs := SimpleModelicaParser.treeDiff(parseTree1, parseTree2, max(listLength(tokens1),listLength(tokens2)));
1114
1115 46 ExecStat.execStat("treeDiff");
1116
1117 46 sanityCheckFailed := false;
1118
1119 if true then
1120 // Do a sanity check
1121 46 s3 := Dump.unparseStr(Parser.parsestring(s2));
1122 46 ExecStat.execStat("sanity parsestring(s2)");
1123 46 s5 := printActual(treeDiffs, SimpleModelicaParser.parseTreeNodeStr);
1124 try
1125 46 s4 := Dump.unparseStr(Parser.parsestring(s5));
1126 46 ExecStat.execStat("sanity parsestring(s5)");
1127 else
1128 ✗ System.writeFile("SanityCheckFail.mo", s5);
1129 ✗ Error.addInternalError("Failed to parse merged string (see generated file SanityCheckFail.mo)\n", sourceInfo());
1130 ✗ fail();
1131 end try;
1132
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if not diffSanityCheckEqual(s3, s4) then
1133 ✗ System.writeFile("SanityCheckFailBefore.mo", s3);
1134 ✗ System.writeFile("SanityCheckFailAfter.mo", s4);
1135 ✗ if b then
1136 ✗ Error.addInternalError("After merging the strings, the semantics changed for some reason (see generated files SanityCheckFailBefore.mo SanityCheckFailAfter.mo). Will return the empty string:\ns1:\n"+s1+"\ns2:\n"+s2+"\ns3:\n"+s3+"\ns4:\n"+s4+"\ns5:\n"+s5+"\nparseTree2:"+SimpleModelicaParser.parseTreeStr(parseTree2), sourceInfo());
1137 ✗ fail();
1138 else
1139 ✗ Error.addInternalError("After merging the strings, the semantics changed for some reason (see generated files SanityCheckFailBefore.mo SanityCheckFailAfter.mo). Will return s2:\ns1:\n"+s1+"\ns2:\n"+s2+"\ns3:\n"+s3+"\ns4:\n"+s4+"\ns5:\n"+s5, sourceInfo());
1140 end if;
1141 sanityCheckFailed := true;
1142 end if;
1143 end if;
1144
1145 /*
1146 diffs := diff(tokens1, tokens2, modelicaDiffTokenEq, modelicaDiffTokenWhitespace, tokenContent);
1147 ExecStat.execStat("diffModelicaFileListings diff 1");
1148 // print("Before filtering:\n"+printDiffTerminalColor(diffs, tokenContent)+"\n");
1149 diffs := filterModelicaDiff(diffs,removeWhitespace=false);
1150 ExecStat.execStat("diffModelicaFileListings filter diff 1");
1151 // Scan a second time, with comments filtered into place
1152 str := printActual(diffs, tokenContent);
1153 // print("Intermediate string:\n"+printDiffTerminalColor(diffs, tokenContent)+"\n");
1154 tokens2 := scanString(str);
1155 ExecStat.execStat("diffModelicaFileListings prepare pass 2");
1156 diffs := diff(tokens1, tokens2, modelicaDiffTokenEq, modelicaDiffTokenWhitespace, tokenContent);
1157 ExecStat.execStat("diffModelicaFileListings diff 2");
1158 // print("Before filtering (2):\n"+printDiffTerminalColor(diffs, tokenContent)+"\n");
1159 diffs := filterModelicaDiff(diffs);
1160 ExecStat.execStat("diffModelicaFileListings filter diff 2");
1161 */
1162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 str := if sanityCheckFailed then s2 else matchcontinue AbsynUtil.pathLastIdent(path)
1163 19 case "plain" then printActual(treeDiffs, SimpleModelicaParser.parseTreeNodeStr);
1164 17 case "color" then printDiffTerminalColor(treeDiffs, SimpleModelicaParser.parseTreeNodeStr);
1165 10 case "xml" then printDiffXml(treeDiffs, SimpleModelicaParser.parseTreeNodeStr);
1166 else
1167 algorithm
1168 ✗ Error.addInternalError("Unknown diffModelicaFileListings choice", sourceInfo());
1169 ✗ then fail();
1170 end matchcontinue;
1171 // Restore the original file's line-ending convention (we processed as LF above).
1172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 str := if lineEndingIsCRLF then System.stringReplace(str, "\n", "\r\n") else str;
1173 46 then
1174 Values.STRING(bom + str);
1175
1176 case ("diffModelicaFileListings",_) then Values.STRING("");
1177
1178 // exportToFigaro cases added by Alexander Carlqvist
1179 case ("exportToFigaro", {Values.CODE(Absyn.C_TYPENAME(path)), Values.STRING(s1), Values.STRING(str), Values.STRING(str1), Values.STRING(str2), Values.STRING(str3)})
1180 algorithm
1181 ✗ sp := SymbolTable.getSCode();
1182 /* The following line of code should be commented out when building from trunk.
1183 Uncomment when bootstrapping. */
1184 ✗ Figaro.run(sp, path, s1, str, str1, str2, str3);
1185 then
1186 Values.BOOL(true);
1187
1188 case ("exportToFigaro", _) then Values.BOOL(false);
1189
1190 case ("inferBindings", {Values.CODE(Absyn.C_TYPENAME(classpath))})
1191 algorithm
1192 ✗ pnew := Binding.inferBindings(classpath, SymbolTable.getAbsyn());
1193 ✗ SymbolTable.setAbsyn(pnew);
1194 then
1195 Values.BOOL(true);
1196
1197 case ("inferBindings", _)
1198 algorithm
1199 ✗ print("failed inferBindings\n");
1200 then
1201 Values.BOOL(false);
1202
1203 case ("generateVerificationScenarios", {Values.CODE(Absyn.C_TYPENAME(classpath))})
1204 algorithm
1205 1 pnew := Binding.generateVerificationScenarios(classpath, SymbolTable.getAbsyn());
1206 1 SymbolTable.setAbsyn(pnew);
1207 then
1208 Values.BOOL(true);
1209
1210 case ("generateVerificationScenarios", _)
1211 algorithm
1212 ✗ print("failed to generateVerificationScenarios\n");
1213 then
1214 Values.BOOL(false);
1215
1216 case ("rewriteBlockCall",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path))})
1217 algorithm
1218 ✗ p := SymbolTable.getAbsyn();
1219 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, p);
1220 classes := {absynClass};
1221 ✗ absynClass := ProgramUtil.getPathedClassInProgram(classpath, p);
1222 ✗ within_ := ProgramUtil.buildWithin(classpath);
1223 ✗ pnew := BlockCallRewrite.rewriteBlockCall(Absyn.PROGRAM({absynClass}, within_), Absyn.PROGRAM(classes, within_));
1224 ✗ pnew := ProgramUtil.updateProgram(pnew, p);
1225 ✗ SymbolTable.setAbsyn(pnew);
1226 ✗ outCache := FCore.emptyCache();
1227 then
1228 Values.BOOL(true);
1229
1230 case ("rewriteBlockCall", _)
1231 then Values.BOOL(false);
1232
1233 case ("jacobian",{Values.CODE(Absyn.C_TYPENAME(path))})
1234 algorithm
1235 ✗ (outCache, env, SOME(dae), _) := runFrontEnd(outCache, inEnv, path, true, transform = true);
1236 ✗ filenameprefix := AbsynUtil.pathString(path);
1237 ✗ description := DAEUtil.daeDescription(dae);
1238 ✗ daelow := BackendDAECreate.lower(dae,outCache,env,BackendDAE.EXTRA_INFO(description,filenameprefix,NONE()));
1239 ✗ BackendDAE.DAE({syst},shared) := BackendDAEUtil.preOptimizeBackendDAE(daelow,NONE());
1240 ✗ (syst,m,_) := BackendDAEUtil.getAdjacencyMatrixfromOption(syst,BackendDAE.NORMAL(),NONE(),BackendDAEUtil.isInitializationDAE(shared));
1241 ✗ vars := BackendVariable.daeVars(syst);
1242 ✗ eqnarr := BackendEquation.getEqnsFromEqSystem(syst);
1243 ✗ (jac, _) := SymbolicJacobian.calculateJacobian(vars, eqnarr, m, false,shared);
1244 ✗ res := BackendDump.dumpJacobianStr(jac);
1245 ✗ then
1246 Values.STRING(res);
1247
1248 case ("translateModel",vals as {Values.CODE(Absyn.C_TYPENAME(className)),_,_,_,_,_,Values.STRING(filenameprefix),_,_,_,_,_})
1249 algorithm
1250 24 (outCache,simSettings) := calculateSimulationSettings(outCache, vals);
1251 24 (b,outCache) := translateModel(outCache, inEnv, className, filenameprefix, true, true, SOME(simSettings));
1252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 then
1253 Values.BOOL(b);
1254
1255 case ("translateModel",_)
1256 then Values.BOOL(false);
1257
1258 case ("modelEquationsUC",{Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(outputFile),Values.BOOL(dumpExtractionSteps)})
1259 algorithm
1260 14 (outCache, ret_val) := Uncertainties.modelEquationsUC(outCache, inEnv, className, outputFile,dumpExtractionSteps);
1261 14 then
1262 ret_val;
1263
1264 case ("modelEquationsUC",_)
1265 then Values.STRING("There were errors during extraction of uncertainty equations. Use getErrorString() to see them.");
1266
1267 case ("translateModelFMU", Values.CODE(Absyn.C_TYPENAME(className))::Values.STRING(str1)::Values.STRING(str2)::Values.STRING(filenameprefix)::Values.ARRAY(valueLst=cvars)::_)
1268 algorithm
1269
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
2 (b, outCache,_) := translateModelFMU(outCache, inEnv, className, str1, str2, filenameprefix, true, list(ValuesUtil.extractValueString(vv) for vv in cvars));
1270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
1271 Values.BOOL(b);
1272
1273 case ("translateModelFMU", _)
1274 then Values.STRING("");
1275
1276 case ("buildModelFMU", Values.CODE(Absyn.C_TYPENAME(className))::Values.STRING(str1)::Values.STRING(str2)::Values.STRING(filenameprefix)::Values.ARRAY(valueLst=cvars)::Values.BOOL(_)::Values.STRING(str3)::_)
1277 algorithm
1278 88 simSettings := fmuSimulationSettings(className, filenameprefix, str3);
1279
4/4
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 88 times.
✓ Branch 3 taken 88 times.
176 (outCache, ret_val) := buildModelFMU(outCache, inEnv, className, str1, str2, filenameprefix, true, list(ValuesUtil.extractValueString(vv) for vv in cvars), SOME(simSettings), str3);
1280 88 then
1281 ret_val;
1282
1283 case ("buildModelFMU", _)
1284 then Values.STRING("");
1285
1286 case ("buildEncryptedPackage", {Values.CODE(Absyn.C_TYPENAME(className)),Values.BOOL(b)})
1287 algorithm
1288 1 p := SymbolTable.getAbsyn();
1289 1 b1 := buildEncryptedPackage(className, b, p);
1290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
1291 Values.BOOL(b1);
1292
1293 case ("buildEncryptedPackage",_)
1294 then Values.BOOL(false);
1295
1296 case ("translateModelXML",{Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(filenameprefix)})
1297 algorithm
1298 ✗ filenameprefix := Util.stringReplaceChar(filenameprefix,".","_");
1299 ✗ (outCache, ret_val) := translateModelXML(outCache, inEnv, className, filenameprefix, true, NONE());
1300 ✗ then
1301 ret_val;
1302
1303 case ("exportDAEtoMatlab",{Values.CODE(Absyn.C_TYPENAME(className)),Values.STRING(filenameprefix)})
1304 algorithm
1305 ✗ (outCache, ret_val, _) := getAdjacencyMatrix(outCache, inEnv, className, msg, filenameprefix);
1306 ✗ then
1307 ret_val;
1308
1309 case ("checkModel",{Values.CODE(Absyn.C_TYPENAME(className))})
1310 algorithm
1311 85 FlagsUtil.setConfigBool(Flags.CHECK_MODEL, true);
1312 85 (outCache, ret_val) := checkModel(outCache, inEnv, className, msg);
1313 85 FlagsUtil.setConfigBool(Flags.CHECK_MODEL, false);
1314 85 then
1315 ret_val;
1316
1317 case ("checkAllModelsRecursive",{Values.CODE(Absyn.C_TYPENAME(className)),Values.BOOL(showProtected)})
1318 algorithm
1319 ✗ (outCache, ret_val) := checkAllModelsRecursive(outCache, inEnv, className, showProtected, msg);
1320 ✗ then
1321 ret_val;
1322
1323 case ("translateGraphics",{Values.CODE(Absyn.C_TYPENAME(className))})
1324 ✗ then translateGraphics(className, msg);
1325
1326 case ("getLoadedLibraries",{})
1327 algorithm
1328 ✗ p := SymbolTable.getAbsyn();
1329 ✗ then
1330 ValuesMake.makeArray(List.fold(p.classes,makeLoadLibrariesEntryAbsyn,{}));
1331
1332 case ("OpenModelica_uriToFilename",{Values.STRING(s1)})
1333 algorithm
1334 ✗ res := OpenModelica.Scripting.uriToFilename(s1);
1335 ✗ if Flags.getConfigBool(Flags.BUILDING_FMU) then
1336 ✗ print("The following path is a loaded resource... "+res+"\n");
1337 ✗ fail();
1338 end if;
1339 ✗ then
1340 Values.STRING(res);
1341
1342 /* Note: Only evaluate uriToFilename during scripting. We need simulations to be able to report URI not found */
1343 case ("OpenModelica_uriToFilename",_)
1344 guard not Flags.getConfigBool(Flags.BUILDING_MODEL)
1345 then Values.STRING("");
1346
1347 case ("getAnnotationVersion",{})
1348 algorithm
1349 4 res := Config.getAnnotationVersion();
1350 4 then
1351 Values.STRING(res);
1352
1353 case ("getNoSimplify",{})
1354 algorithm
1355 ✗ b := Config.getNoSimplify();
1356 ✗ then
1357 Values.BOOL(b);
1358
1359 case ("setNoSimplify",{Values.BOOL(b)})
1360 algorithm
1361 ✗ Config.setNoSimplify(b);
1362 then
1363 Values.BOOL(true);
1364
1365 case ("getShowAnnotations",{})
1366 algorithm
1367 ✗ b := Config.showAnnotations();
1368 ✗ then
1369 Values.BOOL(b);
1370
1371 case ("setShowAnnotations",{Values.BOOL(b)})
1372 algorithm
1373 ✗ Config.setShowAnnotations(b);
1374 then
1375 Values.BOOL(true);
1376
1377 case ("getVectorizationLimit",{})
1378 algorithm
1379 ✗ i := Config.vectorizationLimit();
1380 ✗ then
1381 Values.INTEGER(i);
1382
1383 case ("getOrderConnections",{})
1384 algorithm
1385 ✗ b := Config.orderConnections();
1386 ✗ then
1387 Values.BOOL(b);
1388
1389 case ("buildModel", vals as Values.CODE(Absyn.C_TYPENAME(className))::_)
1390 algorithm
1391 58 List.map_0(ClockIndexes.buildModelClocks,System.realtimeClear);
1392 58 System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL);
1393 58 (b,outCache,compileDir,executable,_,_,initfilename,_,_,vals,_) := buildModel(outCache, inEnv, vals, msg);
1394
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 executable := if not Testsuite.isRunning() then compileDir + executable else executable;
1395
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
114 then
1396 ValuesMake.makeArray(if b then {Values.STRING(executable),Values.STRING(initfilename)} else {Values.STRING(""),Values.STRING("")});
1397
1398 case ("buildModel",_) /* failing build_model */
1399 1 then ValuesMake.makeArray({Values.STRING(""),Values.STRING("")});
1400
1401 case ("buildLabel",vals)
1402 algorithm
1403 ✗ FlagsUtil.setConfigBool(Flags.GENERATE_LABELED_SIMCODE, true);
1404 //FlagsUtil.set(Flags.WRITE_TO_BUFFER,true);
1405 ✗ List.map_0(ClockIndexes.buildModelClocks,System.realtimeClear);
1406 ✗ System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL);
1407 ✗ (b,outCache,_,executable,_,_,initfilename,_,_,vals,_) := buildModel(outCache,inEnv, vals, msg);
1408 ✗ then
1409 ValuesMake.makeArray(if b then {Values.STRING(executable),Values.STRING(initfilename)} else {Values.STRING(""),Values.STRING("")});
1410
1411 case ("reduceTerms",vals)
1412 algorithm
1413 ✗ FlagsUtil.setConfigBool(Flags.REDUCE_TERMS, true);
1414 // FlagsUtil.setConfigBool(Flags.DISABLE_EXTRA_LABELING, true);
1415 ✗ FlagsUtil.setConfigBool(Flags.GENERATE_LABELED_SIMCODE, false);
1416 ✗ FlagsUtil.disableDebug(Flags.WRITE_TO_BUFFER);
1417 ✗ List.map_0(ClockIndexes.buildModelClocks,System.realtimeClear);
1418 ✗ System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL);
1419
1420 ✗ if listLength(vals)<>13 then
1421 ✗ Error.addInternalError("reduceTerms expected 13 arguments", sourceInfo());
1422 end if;
1423 ✗ listGet(vals,13);
1424 ✗ vals:=listDelete(vals,13);
1425 /* labelstoCancel; doesn't do anything */
1426
1427 ✗ (b,outCache,_,executable,_,_,initfilename,_,_,_) := buildModel(outCache,inEnv, vals, msg);
1428 ✗ then
1429 ValuesMake.makeArray(if b then {Values.STRING(executable),Values.STRING(initfilename)} else {Values.STRING(""),Values.STRING("")});
1430
1431 case ("simulate",vals as Values.CODE(Absyn.C_TYPENAME(className))::_)
1432 algorithm
1433 1164 System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL);
1434
1435 // resimulateExecutable is the last (new) argument; pull it off so the rest
1436 // of the pipeline sees the original simulate() argument list.
1437 resimulateExecutable := match List.last(vals) case Values.STRING(str) then str; else ""; end match;
1438 1164 vals := List.stripLast(vals);
1439
1440
3/4
✓ Branch 0 taken 1055 times.
✓ Branch 1 taken 109 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1055 times.
1164 if resimulateExecutable <> "" then
1441 // Skip translation and build; simulate the already-built model directly.
1442 109 b := true;
1443 109 executable := resimulateExecutable;
1444 109 compileDir := System.pwd() + Autoconf.pathDelimiter;
1445 simflags := match List.last(vals) case Values.STRING(str) then str; else ""; end match;
1446 109 resultValues := zeroBuildPhaseResultValues;
1447 else
1448 1055 (b,outCache,compileDir,executable,_,outputFormat_str,_,simflags,resultValues,vals,_) := buildModel(outCache,inEnv,vals,msg);
1449 end if;
1450
1451
2/2
✓ Branch 0 taken 1148 times.
✓ Branch 1 taken 1 time.
1149 if b then
1452 1148 exeDir := compileDir;
1453 1148 (outCache,simSettings) := calculateSimulationSettings(outCache, vals);
1454 1148 SimCode.SIMULATION_SETTINGS(outputFormat = outputFormat_str) := simSettings;
1455 1148 result_file := stringAppendList(List.consOnTrue(not Testsuite.isRunning(),compileDir,{executable,"_res.",outputFormat_str}));
1456 // result file might have been set by simflags (-r ...)
1457
1458 1148 result_file := selectResultFile(result_file, simflags);
1459
1460 1148 executableSuffixedExe := stringAppend(executable, getSimulationExtension(Config.simCodeTarget(),Autoconf.platform));
1461 1148 logFile := stringAppend(executable,".log");
1462 // adrpo: log file is deleted by buildModel! do NOT DELETE IT AGAIN!
1463 // we should really have different log files for simulation/compilation!
1464 // as the buildModel log file will be deleted here and that gives less information to the user!
1465
1/2
✓ Branch 1 taken 1148 times.
✗ Branch 2 not taken.
1148 if System.regularFileExists(logFile) then
1466
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1148 times.
1148 0 := System.removeFile(logFile);
1467 end if;
1468 2296 sim_call := stringAppendList({"\"",exeDir,executableSuffixedExe,"\""," ",simflags});
1469 1148 System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION);
1470 1148 SimulationResults.close() "Windows cannot handle reading and writing to the same file from different processes like any real OS :(";
1471
1472 // The wasm-jit target runs the JIT-compiled model in-process and
1473 // writes the result file directly, instead of spawning an executable;
1474 // the wasm target runs the standalone module in a wasmtime subprocess.
1475
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1148 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
1148 if Config.simCodeTarget() == "wasm-jit" then
1476 ✗ resI := CodegenWasmJit.runSimulation(executable, result_file, simflags);
1477 elseif Config.simCodeTarget() == "wasm" then
1478 ✗ resI := CodegenWasmJit.runSimulationWasmtime(executable, result_file, simflags);
1479 else
1480 1148 resI := System.systemCallRestrictedEnv(sim_call, logFile);
1481 end if;
1482
1483 1148 timeSimulation := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION);
1484
1485 else
1486 result_file := "";
1487 resI := 1;
1488 timeSimulation := 0.0;
1489 logFile := "";
1490 end if;
1491
1492 1149 timeTotal := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL);
1493
1494 1149 (outCache,simValue) := createSimulationResultFromcallModelExecutable(b,resI,timeTotal,timeSimulation,resultValues,outCache,className,vals,result_file,logFile);
1495 1149 then
1496 simValue;
1497
1498 case ("simulate",vals as Values.CODE(Absyn.C_TYPENAME(className))::_)
1499 algorithm
1500 15 Settings.getInstallationDirectoryPath() "simulation fail for some other reason than OPENMODELICAHOME not being set." ;
1501 15 str := AbsynUtil.pathString(className);
1502 15 res := "Failed to build model: " + str;
1503 15 then
1504 createSimulationResultFailure(res, simOptionsAsString(List.stripLast(vals)));
1505
1506 case ("simulate",vals as Values.CODE(Absyn.C_TYPENAME(className))::_)
1507 algorithm
1508 ✗ str := AbsynUtil.pathString(className);
1509 ✗ then
1510 createSimulationResultFailure(
1511 "Simulation failed for model: " + str +
1512 "\nEnvironment variable OPENMODELICAHOME not set.",
1513 simOptionsAsString(List.stripLast(vals)));
1514
1515 case ("moveClass", {Values.CODE(Absyn.C_TYPENAME(className)),
1516 Values.INTEGER(direction)})
1517 algorithm
1518 1 (p, b) := moveClass(className, direction, SymbolTable.getAbsyn());
1519 1 SymbolTable.setAbsyn(p);
1520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
1521 Values.BOOL(b);
1522
1523 case ("moveClass", _) then Values.BOOL(false);
1524
1525 case ("moveClassToTop", {Values.CODE(Absyn.C_TYPENAME(className))})
1526 algorithm
1527 ✗ (p, b) := moveClassToTop(className, SymbolTable.getAbsyn());
1528 ✗ SymbolTable.setAbsyn(p);
1529 ✗ then
1530 Values.BOOL(b);
1531
1532 case ("moveClassToTop", _) then Values.BOOL(false);
1533
1534 case ("moveClassToBottom", {Values.CODE(Absyn.C_TYPENAME(className))})
1535 algorithm
1536 ✗ (p, b) := moveClassToBottom(className, SymbolTable.getAbsyn());
1537 ✗ SymbolTable.setAbsyn(p);
1538 ✗ then
1539 Values.BOOL(b);
1540
1541 case ("moveClassToBottom", _) then Values.BOOL(false);
1542
1543 case ("copyClass",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(name), Values.CODE(Absyn.C_TYPENAME(path))})
1544 algorithm
1545 6 p := SymbolTable.getAbsyn();
1546 6 absynClass := ProgramUtil.getPathedClassInProgram(classpath, p);
1547 6 within_ := InteractiveUtil.parseWithinPath(path);
1548 6 p := copyClass(absynClass, name, within_, classpath, p);
1549 absynClass := ProgramUtil.getPathedClassInProgram(
1550 6 match within_ case Absyn.WITHIN() then ProgramUtil.joinPaths(name, within_.path); else Absyn.IDENT(name); end match, p);
1551 6 SymbolTable.setAbsynLoaded(p, Absyn.PROGRAM({absynClass}, within_));
1552 then
1553 Values.BOOL(true);
1554
1555 case ("copyClass", _) then Values.BOOL(false);
1556
1557 // see if the model exists before linearization!
1558 case ("linearize",vals as Values.CODE(Absyn.C_TYPENAME(className))::_)
1559 algorithm
1560
1/2
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
13 false := Interactive.existClass(className, SymbolTable.getAbsyn());
1561 ✗ errMsg := "Linearization Failed. Model: " + AbsynUtil.pathString(className) + " does not exist! Please load it first before linearization.";
1562 ✗ then
1563 createSimulationResultFailure(errMsg, simOptionsAsString(vals));
1564
1565 case ("linearize",(vals as Values.CODE(Absyn.C_TYPENAME(className))::_))
1566 algorithm
1567 13 System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL);
1568 // Ensure that the linearization dump language is set to modelica if it is none
1569 13 str := Flags.getConfigString(Flags.LINEARIZATION_DUMP_LANGUAGE);
1570
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
13 if (stringEq(str,"none")) then
1571 9 FlagsUtil.setConfigString(Flags.LINEARIZATION_DUMP_LANGUAGE, "modelica");
1572 end if;
1573
1574 13 (b,outCache,compileDir,executable,_,outputFormat_str,_,simflags,resultValues,vals,_) := buildModel(outCache,inEnv,vals,msg);
1575
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if b then
1576
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 Values.REAL(linearizeTime) := getListNthShowError(vals,"try to get stop time",0,2);
1577 13 executableSuffixedExe := stringAppend(executable, getSimulationExtension(Config.simCodeTarget(),Autoconf.platform));
1578 13 logFile := stringAppend(executable,".log");
1579
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 if System.regularFileExists(logFile) then
1580
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 0 := System.removeFile(logFile);
1581 end if;
1582 13 strlinearizeTime := realString(linearizeTime);
1583 13 simflags := "-l=" + strlinearizeTime + " " + simflags;
1584 26 sim_call := stringAppendList({"\"",compileDir,executableSuffixedExe,"\""," ",simflags});
1585 13 System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION);
1586 13 SimulationResults.close() "Windows cannot handle reading and writing to the same file from different processes like any real OS :(";
1587
1588 // The wasm-jit target runs the JIT-compiled model in-process, as `simulate` does.
1589
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
13 if Config.simCodeTarget() == "wasm-jit" then
1590 ✗ result_file := stringAppendList(List.consOnTrue(not Testsuite.isRunning(),compileDir,{executable,"_res.",outputFormat_str}));
1591 ✗ resI := CodegenWasmJit.runSimulation(executable, result_file, simflags);
1592 else
1593 13 resI := System.systemCallRestrictedEnv(sim_call, logFile);
1594 end if;
1595
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if 0 == resI then
1596 26 result_file := stringAppendList(List.consOnTrue(not Testsuite.isRunning(),compileDir,{executable,"_res.",outputFormat_str}));
1597 13 timeSimulation := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION);
1598 13 timeTotal := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL);
1599 26 simValue := createSimulationResult(
1600 result_file,
1601 simOptionsAsString(vals),
1602 System.readFile(logFile),
1603 ("timeTotal", Values.REAL(timeTotal)) ::
1604 ("timeSimulation", Values.REAL(timeSimulation)) ::
1605 resultValues);
1606 13 SymbolTable.addVar(
1607 DAE.CREF_IDENT("currentSimulationResult", DAE.T_STRING_DEFAULT, {}),
1608 Values.STRING(result_file), FGraph.empty());
1609 else
1610 ✗ res := "Succeeding building the linearized executable, but failed to run the linearize command: " + sim_call + "\n" + System.readFile(logFile);
1611 ✗ simValue := createSimulationResultFailure(res, simOptionsAsString(vals));
1612 end if;
1613 else
1614 timeSimulation := 0.0;
1615 ✗ timeTotal := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL);
1616 ✗ simValue := createSimulationResult(
1617 "",
1618 simOptionsAsString(vals),
1619 "Failed to run the linearize command: " + AbsynUtil.pathString(className),
1620 ("timeTotal", Values.REAL(timeTotal)) ::
1621 ("timeSimulation", Values.REAL(timeSimulation)) ::
1622 resultValues);
1623 end if;
1624 13 then
1625 simValue;
1626
1627 case ("linearize",vals as Values.CODE(Absyn.C_TYPENAME(className))::_)
1628 algorithm
1629 ✗ str := AbsynUtil.pathString(className);
1630 ✗ res := "Failed to run the linearize command: " + str;
1631 ✗ then
1632 createSimulationResultFailure(res, simOptionsAsString(vals));
1633
1634 case ("optimize",(vals as Values.CODE(Absyn.C_TYPENAME(className))::_))
1635 algorithm
1636 34 System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL);
1637
1638 34 FlagsUtil.setConfigBool(Flags.GENERATE_SYMBOLIC_LINEARIZATION,true);
1639 34 FlagsUtil.setConfigEnum(Flags.GRAMMAR, Flags.OPTIMICA);
1640 34 FlagsUtil.setConfigBool(Flags.GENERATE_DYN_OPTIMIZATION_PROBLEM,true);
1641
1642 34 (b,outCache,compileDir,executable,_,outputFormat_str,_,simflags,resultValues,vals,_) := buildModel(outCache,inEnv,vals,msg);
1643
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 if b then
1644 34 exeDir:=compileDir;
1645 34 (outCache,simSettings) := calculateSimulationSettings(outCache, vals);
1646 34 SimCode.SIMULATION_SETTINGS(outputFormat = outputFormat_str) := simSettings;
1647 34 result_file := stringAppendList(List.consOnTrue(not Testsuite.isRunning(),compileDir,{executable,"_res.",outputFormat_str}));
1648 34 executableSuffixedExe := stringAppend(executable, getSimulationExtension(Config.simCodeTarget(),Autoconf.platform));
1649 34 logFile := stringAppend(executable,".log");
1650 // adrpo: log file is deleted by buildModel! do NOT DELTE IT AGAIN!
1651 // we should really have different log files for simulation/compilation!
1652 // as the buildModel log file will be deleted here and that gives less information to the user!
1653
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 if System.regularFileExists(logFile) then
1654
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
34 0 := System.removeFile(logFile);
1655 end if;
1656 68 sim_call := stringAppendList({"\"",exeDir,executableSuffixedExe,"\""," ",simflags});
1657 34 System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION);
1658 34 SimulationResults.close() "Windows cannot handle reading and writing to the same file from different processes like any real OS :(";
1659 // As in the simulate() case: the wasm-jit target runs the JIT-compiled
1660 // model in-process instead of spawning an executable.
1661
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
34 if Config.simCodeTarget() == "wasm-jit" then
1662 ✗ resI := CodegenWasmJit.runSimulation(executable, result_file, simflags);
1663 elseif Config.simCodeTarget() == "wasm" then
1664 ✗ resI := CodegenWasmJit.runSimulationWasmtime(executable, result_file, simflags);
1665 else
1666 34 resI := System.systemCallRestrictedEnv(sim_call, logFile);
1667 end if;
1668 34 timeSimulation := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION);
1669 else
1670 result_file := "";
1671 timeSimulation := 0.0;
1672 resI := 1;
1673 logFile := "";
1674 end if;
1675 34 timeTotal := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL);
1676 34 (outCache,simValue) := createSimulationResultFromcallModelExecutable(b,resI,timeTotal,timeSimulation,resultValues,outCache,className,vals,result_file,logFile);
1677 34 then
1678 simValue;
1679
1680 case ("optimize",vals as Values.CODE(Absyn.C_TYPENAME(className))::_)
1681 algorithm
1682 ✗ str := AbsynUtil.pathString(className);
1683 ✗ res := "Failed to run the optimize command: " + str;
1684 ✗ then
1685 createSimulationResultFailure(res, simOptionsAsString(vals));
1686
1687 case ("instantiateModel", {Values.CODE(Absyn.C_TYPENAME(className))})
1688 algorithm
1689 102 (outCache, ret_val) := instantiateModel(outCache, inEnv, className);
1690 102 then
1691 ret_val;
1692
1693 case ("moo",(vals as Values.CODE(Absyn.C_TYPENAME(className))::_))
1694 algorithm
1695 ✗ System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL);
1696
1697 ✗ FlagsUtil.setConfigBool(Flags.GENERATE_SYMBOLIC_LINEARIZATION,true);
1698 ✗ FlagsUtil.setConfigEnum(Flags.GRAMMAR, Flags.OPTIMICA);
1699 ✗ FlagsUtil.setConfigBool(Flags.GENERATE_DYN_OPTIMIZATION_PROBLEM,true);
1700
1701 ✗ (b,outCache,compileDir,executable,_,outputFormat_str,_,simflags,resultValues,vals,_) := buildModel(outCache,inEnv,vals,msg);
1702 ✗ simflags := stringAppend(simflags, " -moo");
1703 ✗ if b then
1704 ✗ exeDir:=compileDir;
1705 ✗ (outCache,simSettings) := calculateSimulationSettings(outCache, vals);
1706 ✗ SimCode.SIMULATION_SETTINGS(outputFormat = outputFormat_str) := simSettings;
1707 ✗ result_file := stringAppendList(List.consOnTrue(not Testsuite.isRunning(),compileDir,{executable,"_res.",outputFormat_str}));
1708 ✗ executableSuffixedExe := stringAppend(executable, getSimulationExtension(Config.simCodeTarget(),Autoconf.platform));
1709 ✗ logFile := stringAppend(executable,".log");
1710 // adrpo: log file is deleted by buildModel! do NOT DELTE IT AGAIN!
1711 // we should really have different log files for simulation/compilation!
1712 // as the buildModel log file will be deleted here and that gives less information to the user!
1713 ✗ if System.regularFileExists(logFile) then
1714 ✗ 0 := System.removeFile(logFile);
1715 end if;
1716 ✗ sim_call := stringAppendList({"\"",exeDir,executableSuffixedExe,"\""," ",simflags});
1717 ✗ System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION);
1718 ✗ SimulationResults.close() "Windows cannot handle reading and writing to the same file from different processes like any real OS :(";
1719 ✗ resI := System.systemCallRestrictedEnv(sim_call, logFile);
1720 ✗ timeSimulation := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_SIMULATION);
1721 else
1722 result_file := "";
1723 timeSimulation := 0.0;
1724 resI := 1;
1725 logFile := "";
1726 end if;
1727 ✗ timeTotal := System.realtimeTock(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL);
1728 ✗ (outCache,simValue) := createSimulationResultFromcallModelExecutable(b,resI,timeTotal,timeSimulation,resultValues,outCache,className,vals,result_file,logFile);
1729 ✗ then
1730 simValue;
1731
1732 case ("moo",vals as Values.CODE(Absyn.C_TYPENAME(className))::_)
1733 algorithm
1734 ✗ str := AbsynUtil.pathString(className);
1735 ✗ res := "Failed to run the moo command: " + str;
1736 ✗ then
1737 createSimulationResultFailure(res, simOptionsAsString(vals));
1738
1739 case ("importFMU",{Values.STRING(filename),Values.STRING(workdir),Values.INTEGER(fmiLogLevel),Values.BOOL(b1), Values.BOOL(b2), Values.BOOL(inputConnectors), Values.BOOL(outputConnectors), Values.CODE(Absyn.C_TYPENAME(classpath))})
1740 algorithm
1741 18 Error.clearMessages() "Clear messages";
1742
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 true := System.regularFileExists(filename);
1743
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 workdir := if System.directoryExists(workdir) then workdir else System.pwd();
1744 /* Initialize FMI objects */
1745 18 (b, fmiContext, fmiInstance, fmiInfo, fmiTypeDefinitionsList, fmiExperimentAnnotation, fmiModelVariablesInstance, fmiModelVariablesList) := FMIExt.initializeFMIImport(filename, workdir, fmiLogLevel, inputConnectors, outputConnectors);
1746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 true := b; /* if something goes wrong while initializing */
1747 18 fmiTypeDefinitionsList := listReverse(fmiTypeDefinitionsList);
1748 18 fmiModelVariablesList := listReverse(fmiModelVariablesList);
1749 18 s1 := System.tolower(Autoconf.platform);
1750 18 name := AbsynUtil.pathString(classpath);
1751
2/8
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
18 name := if stringEq(name, "Default") or stringEq(name, "default") then "" else name;
1752
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
36 str := Tpl.tplString2(CodegenFMU.importFMUModelica, FMI.FMIIMPORT(s1, filename, workdir, fmiLogLevel, b2, fmiContext, fmiInstance, fmiInfo, fmiTypeDefinitionsList, fmiExperimentAnnotation, fmiModelVariablesInstance, fmiModelVariablesList, inputConnectors, outputConnectors), name);
1753 pd := Autoconf.pathDelimiter;
1754 18 str1 := FMI.getFMIModelIdentifier(fmiInfo);
1755 18 str2 := FMI.getFMIType(fmiInfo);
1756 18 str3 := FMI.getFMIVersion(fmiInfo);
1757
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
36 outputFile := if stringEmpty(name) then stringAppendList({str1,"_",str2,"_FMU.mo"}) else stringAppendList({name,".mo"});
1758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 filename_1 := if b1 then stringAppendList({workdir,pd,outputFile}) else outputFile;
1759 18 System.writeFile(stringAppendList({workdir,pd,outputFile}), str);
1760 /* Release FMI objects */
1761 18 FMIExt.releaseFMIImport(fmiModelVariablesInstance, fmiInstance, fmiContext, str3);
1762 18 then
1763 Values.STRING(filename_1);
1764
1765 case ("importFMU",{Values.STRING(filename),Values.STRING(_),Values.INTEGER(_),Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.CODE(_)})
1766 algorithm
1767 ✗ false := System.regularFileExists(filename);
1768 ✗ Error.clearMessages() "Clear messages";
1769 ✗ Error.addMessage(Error.FILE_NOT_FOUND_ERROR, {filename});
1770 then
1771 Values.STRING("");
1772
1773 case ("importFMU",{Values.STRING(_),Values.STRING(_),Values.INTEGER(_),Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.CODE(_)})
1774 then
1775 Values.STRING("");
1776
1777 case ("importFMUModelDescription",{Values.STRING(filename), Values.STRING(workdir),Values.INTEGER(fmiLogLevel),Values.BOOL(b1), Values.BOOL(b2), Values.BOOL(inputConnectors), Values.BOOL(outputConnectors)})
1778 algorithm
1779 ✗ Error.clearMessages() "Clear messages";
1780 ✗ true := System.regularFileExists(filename);
1781 ✗ workdir := if System.directoryExists(workdir) then workdir else System.pwd();
1782 // create a temporary directory
1783 ✗ tmpDir := System.createTemporaryDirectory(Settings.getTempDirectoryPath() + "/" + "fmuTmp" + intString(System.intRand(1000)));
1784 ✗ tmpFile := tmpDir + "/" + "modelDescription.xml";
1785 ✗ System.systemCall("cp -f " + filename + " " + tmpFile);
1786 ✗ modeldescriptionfilename := tmpDir + "/modelDescription.fmu";
1787 ✗ System.systemCall("zip -j " + modeldescriptionfilename + " " + tmpFile);
1788 ✗ true := System.regularFileExists(modeldescriptionfilename);
1789 /* Initialize FMI objects */
1790 ✗ (b, fmiContext, fmiInstance, fmiInfo, fmiTypeDefinitionsList, fmiExperimentAnnotation, fmiModelVariablesInstance, fmiModelVariablesList) :=
1791 FMIExt.initializeFMIImport(modeldescriptionfilename, tmpDir, fmiLogLevel, inputConnectors, outputConnectors, true);
1792 ✗ true := b; /* if something goes wrong while initializing */
1793 ✗ fmiTypeDefinitionsList := listReverse(fmiTypeDefinitionsList);
1794 ✗ fmiModelVariablesList := listReverse(fmiModelVariablesList);
1795 ✗ s1 := System.tolower(Autoconf.platform);
1796 ✗ str := Tpl.tplString(CodegenFMU.importFMUModelDescription, FMI.FMIIMPORT(s1, modeldescriptionfilename, workdir, fmiLogLevel, b2, fmiContext, fmiInstance, fmiInfo, fmiTypeDefinitionsList, fmiExperimentAnnotation, fmiModelVariablesInstance, fmiModelVariablesList, inputConnectors, outputConnectors));
1797 pd := Autoconf.pathDelimiter;
1798 ✗ str1 := FMI.getFMIModelIdentifier(fmiInfo);
1799 ✗ str3 := FMI.getFMIVersion(fmiInfo);
1800 ✗ outputFile := stringAppendList({workdir,pd,str1,"_Input_Output_FMU.mo"});
1801 ✗ filename_1 := if b1 then stringAppendList({workdir,pd,str1,"_Input_Output_FMU.mo"}) else stringAppendList({str1,"_Input_Output_FMU.mo"});
1802 ✗ System.writeFile(outputFile, str);
1803 /* Release FMI objects */
1804 ✗ FMIExt.releaseFMIImport(fmiModelVariablesInstance, fmiInstance, fmiContext, str3);
1805 ✗ System.removeDirectory(tmpDir);
1806 ✗ then
1807 Values.STRING(filename_1);
1808
1809 case ("importFMUModelDescription",{Values.STRING(filename),Values.STRING(_),Values.INTEGER(_),Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.BOOL(_)})
1810 algorithm
1811 ✗ if not System.regularFileExists(filename) then
1812 ✗ Error.addMessage(Error.FILE_NOT_FOUND_ERROR, {filename});
1813 end if;
1814 then
1815 Values.STRING("");
1816
1817 case ("importFMUModelDescription",{Values.STRING(_),Values.STRING(_),Values.INTEGER(_),Values.BOOL(_), Values.BOOL(_), Values.BOOL(_), Values.BOOL(_)})
1818 then
1819 Values.STRING("");
1820
1821 case ("getIndexReductionMethod",_)
1822 algorithm
1823 ✗ str := Config.getIndexReductionMethod();
1824 ✗ then
1825 Values.STRING(str);
1826
1827 case ("getAvailableIndexReductionMethods",_)
1828 algorithm
1829 ✗ (strs1,strs2) := FlagsUtil.getConfigOptionsStringList(Flags.INDEX_REDUCTION_METHOD);
1830 ✗ v1 := ValuesMake.makeArray(List.map(strs1, ValuesMake.makeString));
1831 ✗ v2 := ValuesMake.makeArray(List.map(strs2, ValuesMake.makeString));
1832 ✗ then
1833 Values.TUPLE({v1,v2});
1834
1835 else
1836 algorithm
1837 5099 (outCache, ret_val) := cevalInteractiveFunctions4(inCache,inEnv,inFunctionName,inVals,msg);
1838 4077 then
1839 ret_val;
1840
1841 end matchcontinue;
1842 end cevalInteractiveFunctions3;
1843
1844 public function cevalInteractiveFunctions4
1845 "defined in the interactive environment."
1846 input FCore.Cache inCache;
1847 input FCore.Graph inEnv;
1848 input String inFunctionName;
1849 input list<Values.Value> inVals;
1850 input Absyn.Msg msg;
1851 output FCore.Cache outCache = inCache;
1852 output Values.Value outValue;
1853 protected
1854 import LexerModelicaDiff.{Token,TokenId,tokenContent,scanString,reportErrors,filterModelicaDiff,modelicaDiffTokenEq,modelicaDiffTokenWhitespace};
1855 import DiffAlgorithm.{Diff,diff,printActual,printDiffTerminalColor,printDiffXml};
1856 algorithm
1857 outValue := matchcontinue (inFunctionName, inVals)
1858 local
1859 String s1,s2,str,str1,str2,str3,str4,method_str, pd,filename_1,filename,
1860 call,name, title,xLabel,yLabel,yLabelRight,filename2,varNameStr,xml_filename,pwd,omhome,os,
1861 gridStr, logXStr, logYStr, x1Str, x2Str, y1Str, y2Str, yAxis, curveWidthStr, curveStyleStr, legendPosition, footer, autoScaleStr,
1862 cname, annStr, annotationname, modifiername;
1863 list<Values.Value> vals,cvars;
1864 Absyn.Path path,classpath,baseClassPath;
1865 Interactive.GraphicEnvCache genv;
1866 Absyn.Program p,newp;
1867 InteractiveTypes.SimulationOptions simOpt;
1868 Real startTime,stopTime,tolerance,reltol,reltolDiffMinMax,rangeDelta;
1869 DAE.Exp startTimeExp,stopTimeExp,toleranceExp,intervalExp;
1870 DAE.Type tp;
1871 Absyn.Class absynClass;
1872 Absyn.Exp aexp, aexp2, aexp3;
1873 Option<DAE.DAElist> odae;
1874 Values.Value v,cvar,cvar2,v1,v2;
1875 Absyn.ComponentRef cr, cr2;
1876 Integer size,i,n,curveStyle,numberOfIntervals,x,y;
1877 Access access;
1878 list<String> vars_1,args,strings,strs1,strs2,files;
1879 Real timeStamp,val,x1,x2,y1,y2,y1R,y2R,r1,r2,curveWidth, interval;
1880 GlobalScript.Statements istmts;
1881 Boolean b, b1, b2, b3, externalWindow, logX, logY, autoScale, forceOMPlot, keepRedeclares, hintReadAllVars;
1882 list<Real> realVals;
1883 list<Absyn.Path> paths;
1884 list<Absyn.NamedArg> nargs;
1885 list<Absyn.ElementArg> annlst;
1886 list<tuple<Absyn.Path,String,list<String>,Boolean>> uses;
1887 list<String> withoutConversion, withConversion;
1888 list<tuple<String,String>> relocatableFunctionsTuple;
1889 list<list<Values.Value>> valsLst;
1890 System.StatFileType statFileType;
1891 Absyn.Modification mod;
1892
1893 case ("getAvailableIndexReductionMethods",_)
1894 algorithm
1895 ✗ (strs1,strs2) := FlagsUtil.getConfigOptionsStringList(Flags.INDEX_REDUCTION_METHOD);
1896 ✗ v1 := ValuesMake.makeArray(List.map(strs1, ValuesMake.makeString));
1897 ✗ v2 := ValuesMake.makeArray(List.map(strs2, ValuesMake.makeString));
1898 ✗ then
1899 Values.TUPLE({v1,v2});
1900
1901 case ("getMatchingAlgorithm",_)
1902 ✗ then Values.STRING(Config.getMatchingAlgorithm());
1903
1904 case ("getAvailableMatchingAlgorithms",_)
1905 algorithm
1906 ✗ (strs1,strs2) := FlagsUtil.getConfigOptionsStringList(Flags.MATCHING_ALGORITHM);
1907 ✗ v1 := ValuesMake.makeArray(List.map(strs1, ValuesMake.makeString));
1908 ✗ v2 := ValuesMake.makeArray(List.map(strs2, ValuesMake.makeString));
1909 ✗ then
1910 Values.TUPLE({v1,v2});
1911
1912 case ("getTearingMethod",_)
1913 ✗ then Values.STRING(Config.getTearingMethod());
1914
1915 case ("getAvailableTearingMethods",_)
1916 algorithm
1917 ✗ (strs1,strs2) := FlagsUtil.getConfigOptionsStringList(Flags.TEARING_METHOD);
1918 ✗ v1 := ValuesMake.makeArray(List.map(strs1, ValuesMake.makeString));
1919 ✗ v2 := ValuesMake.makeArray(List.map(strs2, ValuesMake.makeString));
1920 ✗ then
1921 Values.TUPLE({v1,v2});
1922
1923 case ("saveModel",{Values.STRING(filename),Values.CODE(Absyn.C_TYPENAME(classpath))})
1924 algorithm
1925 ✗ b := false;
1926 ✗ access := Interactive.checkAccessAnnotationAndEncryption(classpath, SymbolTable.getAbsyn());
1927 ✗ if access >= Access.all then // i.e., The class is not encrypted.
1928 ✗ absynClass := ProgramUtil.getPathedClassInProgram(classpath, SymbolTable.getAbsyn());
1929 ✗ str := Dump.unparseStr(Absyn.PROGRAM({absynClass},Absyn.TOP()),true);
1930 try
1931 ✗ System.writeFile(filename, str);
1932 ✗ b := true;
1933 else
1934 ✗ Error.addMessage(Error.WRITING_FILE_ERROR, {filename});
1935 end try;
1936 else
1937 ✗ Error.addMessage(Error.SAVE_ENCRYPTED_CLASS_ERROR, {});
1938 ✗ b := false;
1939 end if;
1940 ✗ then
1941 Values.BOOL(b);
1942
1943 case ("save",{Values.CODE(Absyn.C_TYPENAME(classpath))})
1944 algorithm
1945 ✗ access := Interactive.checkAccessAnnotationAndEncryption(classpath, SymbolTable.getAbsyn());
1946 ✗ if access >= Access.all then // i.e., The class is not encrypted.
1947 ✗ (newp,filename) := Interactive.getContainedClassAndFile(classpath, SymbolTable.getAbsyn());
1948 ✗ str := Dump.unparseStr(newp);
1949 ✗ System.writeFile(filename, str);
1950 ✗ b := true;
1951 else
1952 ✗ Error.addMessage(Error.SAVE_ENCRYPTED_CLASS_ERROR, {});
1953 ✗ b := false;
1954 end if;
1955 ✗ then
1956 Values.BOOL(b);
1957
1958 case ("save",{Values.CODE(Absyn.C_TYPENAME(_))})
1959 then Values.BOOL(false);
1960
1961 case ("saveAll",{Values.STRING(filename)})
1962 algorithm
1963 ✗ str := Dump.unparseStr(SymbolTable.getAbsyn(),true);
1964 ✗ System.writeFile(filename, str);
1965 then
1966 Values.BOOL(true);
1967
1968 case ("saveModel",{Values.STRING(_),Values.CODE(Absyn.C_TYPENAME(classpath))})
1969 algorithm
1970 ✗ cname := AbsynUtil.pathString(classpath);
1971 ✗ Error.addMessage(Error.LOOKUP_ERROR, {cname,"global"});
1972 then
1973 Values.BOOL(false);
1974
1975 case ("getTotalModel",{Values.CODE(Absyn.C_TYPENAME(classpath)),
1976 Values.BOOL(b1), Values.BOOL(b2), Values.BOOL(b3)})
1977 algorithm
1978 ✗ access := Interactive.checkAccessAnnotationAndEncryption(classpath, SymbolTable.getAbsyn());
1979 ✗ if access >= Access.all then
1980 ✗ s1 := getTotalModel(classpath, b1, b2, b3);
1981 else
1982 ✗ Error.addMessage(Error.SAVE_ENCRYPTED_CLASS_ERROR, {});
1983 s1 := "";
1984 end if;
1985 ✗ then
1986 Values.STRING(s1);
1987
1988 case ("getTotalModel",{Values.CODE(Absyn.C_TYPENAME(_)),
1989 Values.BOOL(_), Values.BOOL(_), Values.BOOL(_)})
1990 then Values.STRING("");
1991
1992 case ("saveTotalModel",{Values.STRING(filename),Values.CODE(Absyn.C_TYPENAME(classpath)),
1993 Values.BOOL(b1), Values.BOOL(b2), Values.BOOL(b3)})
1994 algorithm
1995 4 access := Interactive.checkAccessAnnotationAndEncryption(classpath, SymbolTable.getAbsyn());
1996
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if access >= Access.all then
1997 4 saveTotalModel(filename, classpath, b1, b2, b3);
1998 4 b := true;
1999 else
2000 ✗ Error.addMessage(Error.SAVE_ENCRYPTED_CLASS_ERROR, {});
2001 ✗ b := false;
2002 end if;
2003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 then
2004 Values.BOOL(b);
2005
2006 case ("saveTotalModel",{Values.STRING(_),Values.CODE(Absyn.C_TYPENAME(_)),
2007 Values.BOOL(_), Values.BOOL(_), Values.BOOL(_)})
2008 then Values.BOOL(false);
2009
2010 case ("previous_saveTotalModel",{Values.STRING(filename),Values.CODE(Absyn.C_TYPENAME(classpath)),
2011 Values.BOOL(b1), Values.BOOL(b2), Values.BOOL(b3)})
2012 algorithm
2013 1 access := Interactive.checkAccessAnnotationAndEncryption(classpath, SymbolTable.getAbsyn());
2014
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if access >= Access.all then
2015 1 saveTotalModel(filename, classpath, b1, b2, b3, previous = true);
2016 1 b := true;
2017 else
2018 ✗ Error.addMessage(Error.SAVE_ENCRYPTED_CLASS_ERROR, {});
2019 ✗ b := false;
2020 end if;
2021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
2022 Values.BOOL(b);
2023
2024 case ("previous_saveTotalModel",{Values.STRING(_),Values.CODE(Absyn.C_TYPENAME(_)),
2025 Values.BOOL(_), Values.BOOL(_), Values.BOOL(_)})
2026 then Values.BOOL(false);
2027
2028 case ("saveTotalModelDebug",{Values.STRING(filename),Values.CODE(Absyn.C_TYPENAME(classpath)),
2029 Values.BOOL(b1), Values.BOOL(b2), Values.BOOL(b3)})
2030 algorithm
2031 ✗ access := Interactive.checkAccessAnnotationAndEncryption(classpath, SymbolTable.getAbsyn());
2032 ✗ if access >= Access.all then // i.e., Access.documentation
2033 ✗ saveTotalModelDebug(filename, classpath, b1, b2, b3);
2034 ✗ b := true;
2035 else
2036 ✗ Error.addMessage(Error.SAVE_ENCRYPTED_CLASS_ERROR, {});
2037 ✗ b := false;
2038 end if;
2039 ✗ then
2040 Values.BOOL(b);
2041
2042 case ("saveTotalModelDebug",{Values.STRING(_),Values.CODE(Absyn.C_TYPENAME(_))})
2043 then Values.BOOL(false);
2044
2045 case ("getDocumentationAnnotation",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2046 algorithm
2047 3 access := Interactive.checkAccessAnnotationAndEncryption(classpath, SymbolTable.getAbsyn());
2048
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if access >= Access.documentation then
2049 3 (str1,str2,str3) := ProgramUtil.getNamedAnnotationExp(classpath, SymbolTable.getAbsyn(), Absyn.IDENT("Documentation"), SOME(("","","")),Interactive.getDocumentationAnnotationString);
2050 else
2051 ✗ Error.addMessage(Error.ACCESS_ENCRYPTED_PROTECTED_CONTENTS, {});
2052 (str1,str2,str3) := ("", "", "");
2053 end if;
2054 6 then
2055 ValuesMake.makeArray({Values.STRING(str1),Values.STRING(str2),Values.STRING(str3)});
2056
2057 case ("addClassAnnotation",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.CODE(Absyn.C_EXPRESSION(aexp))})
2058 algorithm
2059 16 p := Interactive.addClassAnnotation(AbsynUtil.pathToCref(classpath), Absyn.NAMEDARG("annotate",aexp)::{}, SymbolTable.getAbsyn());
2060 8 SymbolTable.setAbsyn(p);
2061 then
2062 Values.BOOL(true);
2063
2064 case ("addClassAnnotation",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.CODE(Absyn.C_MODIFICATION(Absyn.CLASSMOD(elementArgLst=annlst,eqMod=Absyn.NOMOD())))})
2065 algorithm
2066 ✗ p := SymbolTable.getAbsyn();
2067 ✗ absynClass := ProgramUtil.getPathedClassInProgram(classpath, p);
2068 ✗ absynClass := Interactive.addClassAnnotationToClass(absynClass, Absyn.ANNOTATION(annlst));
2069 ✗ p := ProgramUtil.updateProgram(Absyn.PROGRAM({absynClass}, if AbsynUtil.pathIsIdent(classpath) then Absyn.TOP() else Absyn.WITHIN(AbsynUtil.stripLast(classpath))), p);
2070 ✗ SymbolTable.setAbsyn(p);
2071 then
2072 Values.BOOL(true);
2073
2074 case ("addClassAnnotation",_)
2075 then Values.BOOL(false);
2076
2077 case ("setDocumentationAnnotation",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.STRING(str1),Values.STRING(str2)})
2078 algorithm
2079 ✗ p := SymbolTable.getAbsyn();
2080 ✗ nargs := List.consOnTrue(not stringEq(str1,""), Absyn.NAMEDARG("info",Absyn.STRING(System.escapedString(str1,false))), {});
2081 ✗ nargs := List.consOnTrue(not stringEq(str2,""), Absyn.NAMEDARG("revisions",Absyn.STRING(System.escapedString(str2,false))), nargs);
2082 ✗ aexp := Absyn.CALL(Absyn.CREF_IDENT("Documentation",{}),Absyn.FUNCTIONARGS({},nargs),{});
2083 ✗ p := Interactive.addClassAnnotation(AbsynUtil.pathToCref(classpath), Absyn.NAMEDARG("annotate",aexp)::{}, p);
2084 ✗ SymbolTable.setAbsyn(p);
2085 then
2086 Values.BOOL(true);
2087
2088 case ("setDocumentationAnnotation",_)
2089 then Values.BOOL(false);
2090
2091 case ("stat",{Values.STRING(str)})
2092 algorithm
2093 278 (b,r1,r2) := System.stat(str);
2094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 278 times.
556 then Values.TUPLE({Values.BOOL(b),Values.REAL(r1),Values.REAL(r2)});
2095
2096 case ("regularFileExists",{Values.STRING(str)})
2097 algorithm
2098 289 (_,_,_,statFileType) := System.stat(str);
2099
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 285 times.
293 then Values.BOOL(statFileType==System.StatFileType.RegularFile);
2100
2101 case ("directoryExists",{Values.STRING(str)})
2102 algorithm
2103 ✗ (_,_,_,statFileType) := System.stat(str);
2104 ✗ then Values.BOOL(statFileType==System.StatFileType.Directory);
2105
2106 case ("OpenModelicaInternal_fullPathName",{Values.STRING(str)})
2107 ✗ then Values.STRING(System.realpath(str));
2108
2109 case ("isType",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2110 algorithm
2111 ✗ b := Interactive.isType(classpath, SymbolTable.getAbsyn());
2112 ✗ then
2113 Values.BOOL(b);
2114
2115 case ("isPackage",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2116 algorithm
2117 ✗ b := Interactive.isPackage(classpath, SymbolTable.getAbsyn());
2118 ✗ then
2119 Values.BOOL(b);
2120
2121 case ("isClass",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2122 algorithm
2123 ✗ b := Interactive.isClass(classpath, SymbolTable.getAbsyn());
2124 ✗ then
2125 Values.BOOL(b);
2126
2127 case ("isRecord",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2128 algorithm
2129 ✗ b := Interactive.isRecord(classpath, SymbolTable.getAbsyn());
2130 ✗ then
2131 Values.BOOL(b);
2132
2133 case ("isBlock",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2134 algorithm
2135 ✗ b := Interactive.isBlock(classpath, SymbolTable.getAbsyn());
2136 ✗ then
2137 Values.BOOL(b);
2138
2139 case ("isFunction",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2140 algorithm
2141 ✗ b := Interactive.isFunction(classpath, SymbolTable.getAbsyn());
2142 ✗ then
2143 Values.BOOL(b);
2144
2145 case ("isPartial",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2146 algorithm
2147 ✗ b := Interactive.isPartial(classpath, SymbolTable.getAbsyn());
2148 ✗ then
2149 Values.BOOL(b);
2150
2151 case ("isReplaceable",{Values.CODE(Absyn.C_TYPENAME(path))})
2152 algorithm
2153 ✗ b := Interactive.isReplaceable(path, SymbolTable.getAbsyn());
2154 ✗ then
2155 Values.BOOL(b);
2156
2157 case ("isRedeclare",{Values.CODE(Absyn.C_TYPENAME(path))})
2158 algorithm
2159 5 b := Interactive.isRedeclare(path, SymbolTable.getAbsyn());
2160
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
8 then
2161 Values.BOOL(b);
2162
2163 case ("isModel",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2164 algorithm
2165 ✗ b := Interactive.isModel(classpath, SymbolTable.getAbsyn());
2166 ✗ then
2167 Values.BOOL(b);
2168
2169 case ("isConnector",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2170 algorithm
2171 ✗ b := Interactive.isConnector(classpath, SymbolTable.getAbsyn());
2172 ✗ then
2173 Values.BOOL(b);
2174
2175 case ("isOptimization",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2176 algorithm
2177 ✗ b := Interactive.isOptimization(classpath, SymbolTable.getAbsyn());
2178 ✗ then
2179 Values.BOOL(b);
2180
2181 case ("isEnumeration",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2182 algorithm
2183 ✗ b := Interactive.isEnumeration(classpath, SymbolTable.getAbsyn());
2184 ✗ then
2185 Values.BOOL(b);
2186
2187 case ("isOperator",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2188 algorithm
2189 ✗ b := Interactive.isOperator(classpath, SymbolTable.getAbsyn());
2190 ✗ then
2191 Values.BOOL(b);
2192
2193 case ("isOperatorRecord",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2194 algorithm
2195 ✗ b := Interactive.isOperatorRecord(classpath, SymbolTable.getAbsyn());
2196 ✗ then
2197 Values.BOOL(b);
2198
2199 case ("isOperatorFunction",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2200 algorithm
2201 ✗ b := Interactive.isOperatorFunction(classpath, SymbolTable.getAbsyn());
2202 ✗ then
2203 Values.BOOL(b);
2204
2205 case ("isProtectedClass",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(name)})
2206 algorithm
2207 ✗ b := Interactive.isProtectedClass(classpath, name, SymbolTable.getAbsyn());
2208 ✗ then
2209 Values.BOOL(b);
2210
2211 case ("getBuiltinType",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2212 algorithm
2213 ✗ (_, tp, _) := Lookup.lookupType(outCache, inEnv, classpath, SOME(Absyn.dummyInfo));
2214 ✗ str := TypesDump.unparseType(tp);
2215 ✗ then
2216 Values.STRING(str);
2217
2218 // if the lookup fails
2219 case ("getBuiltinType",{Values.CODE(Absyn.C_TYPENAME(_))})
2220 then Values.STRING("");
2221
2222 case ("extendsFrom",
2223 {Values.CODE(Absyn.C_TYPENAME(classpath)),
2224 Values.CODE(Absyn.C_TYPENAME(baseClassPath))})
2225 algorithm
2226 ✗ paths := Interactive.getAllInheritedClasses(classpath, SymbolTable.getAbsyn());
2227 ✗ b := List.applyAndFold1(paths, boolOr, AbsynUtil.pathSuffixOfr, baseClassPath, false);
2228 ✗ then
2229 Values.BOOL(b);
2230
2231 case ("extendsFrom",_)
2232 then Values.BOOL(false);
2233
2234 case ("isExperiment",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2235
2/2
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 3 times.
13 then Values.BOOL(isExperiment(classpath, SymbolTable.getAbsyn()));
2236
2237 case ("getInheritedClasses",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2238 algorithm
2239 7 paths := Interactive.getInheritedClasses(classpath);
2240 7 then
2241 ValuesMake.makeCodeTypeNameArray(paths);
2242
2243 case ("getInheritedClasses",_)
2244 ✗ then ValuesMake.makeArray({});
2245
2246 case ("getComponentsTest",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2247 algorithm
2248 1 absynClass := ProgramUtil.getPathedClassInProgram(classpath, SymbolTable.getAbsyn());
2249 1 genv := Interactive.getClassEnv(SymbolTable.getAbsyn(), classpath);
2250
4/4
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1 time.
7 valsLst := list(getComponentInfo(c, genv, isProtected=false) for c in InteractiveUtil.getPublicComponentsInClass(absynClass));
2251
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
1 valsLst := listAppend(list(getComponentInfo(c, genv, isProtected=true) for c in InteractiveUtil.getProtectedComponentsInClass(absynClass)), valsLst);
2252 1 then ValuesMake.makeArray(List.flatten(valsLst));
2253
2254 case ("getComponentsTest",{Values.CODE(Absyn.C_TYPENAME(_))})
2255 ✗ then ValuesMake.makeArray({});
2256
2257 case ("getSimulationOptions",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.REAL(startTime),Values.REAL(stopTime),Values.REAL(tolerance),Values.INTEGER(numberOfIntervals),Values.REAL(interval)})
2258 algorithm
2259 2 cr := AbsynUtil.pathToCref(classpath);
2260 // ignore the name of the model
2261 2 ErrorExt.setCheckpoint("getSimulationOptions");
2262 2 simOpt := InteractiveTypes.SIMULATION_OPTIONS(DAE.RCONST(startTime),DAE.RCONST(stopTime),DAE.ICONST(numberOfIntervals),DAE.RCONST(0.0),DAE.RCONST(tolerance),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST(""),DAE.SCONST(""));
2263 2 ErrorExt.rollBack("getSimulationOptions");
2264
5/10
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
4 (_, _::startTimeExp::stopTimeExp::intervalExp::toleranceExp::_) := StaticScript.getSimulationArguments(FCore.emptyCache(), FGraph.empty(), {Absyn.CREF(cr)},{},false,DAE.NOPRE(), "getSimulationOptions", Absyn.dummyInfo,SOME(simOpt));
2265 2 startTime := ValuesUtil.valueReal(Util.makeValueOrDefault(Ceval.cevalSimple,startTimeExp,Values.REAL(startTime)));
2266 2 stopTime := ValuesUtil.valueReal(Util.makeValueOrDefault(Ceval.cevalSimple,stopTimeExp,Values.REAL(stopTime)));
2267 2 tolerance := ValuesUtil.valueReal(Util.makeValueOrDefault(Ceval.cevalSimple,toleranceExp,Values.REAL(tolerance)));
2268
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 Values.INTEGER(numberOfIntervals) := Util.makeValueOrDefault(Ceval.cevalSimple,intervalExp,Values.INTEGER(numberOfIntervals)); // number of intervals
2269
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if numberOfIntervals == 0 and interval > 0.0 then
2270 ✗ numberOfIntervals := integer(ceil((stopTime - startTime)/interval));
2271 else
2272 // What simulate() runs (SimCodeMain.createSimulationSettings): an
2273 // Interval annotation longer than the experiment is one step to stopTime.
2274 numberOfIntervals := max(numberOfIntervals, 1);
2275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 interval := (stopTime-startTime) / numberOfIntervals;
2276 end if;
2277 4 then
2278 Values.TUPLE({Values.REAL(startTime), Values.REAL(stopTime), Values.REAL(tolerance), Values.INTEGER(numberOfIntervals), Values.REAL(interval)});
2279
2280 case ("getModelFigures",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2281 ✗ then getModelFigures(classpath, SymbolTable.getAbsyn());
2282
2283 case ("getAnnotationNamedModifiers",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.STRING(annotationname)})
2284 2 then getAnnotationNamedModifiers(classpath, annotationname, SymbolTable.getAbsyn());
2285
2286 case ("getAnnotationModifierValue",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.STRING(annotationname),Values.STRING(modifiername)})
2287 4 then getAnnotationModifierValue(classpath, annotationname, modifiername, SymbolTable.getAbsyn());
2288
2289 case ("searchClassNames",{Values.STRING(str), Values.BOOL(b)})
2290 algorithm
2291 ✗ (_,paths) := ProgramUtil.getClassNamesRecursive(NONE(),SymbolTable.getAbsyn(),false,false,{});
2292 ✗ paths := listReverse(paths);
2293 ✗ vals := List.map(paths,ValuesMake.makeCodeTypeName);
2294 ✗ vals := searchClassNames(vals, str, b, SymbolTable.getAbsyn());
2295 ✗ then
2296 ValuesMake.makeArray(vals);
2297
2298 case ("getAvailableLibraries",{})
2299 algorithm
2300 ✗ PackageManagement.installCachedPackages();
2301 ✗ files := PackageManagement.AvailableLibraries.listKeys(PackageManagement.getInstalledLibraries());
2302 ✗ then
2303 ValuesMake.makeArray(List.map(files, ValuesMake.makeString));
2304
2305 case ("getAvailableLibraryVersions",{Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT(str1)))})
2306 algorithm
2307 ✗ PackageManagement.installCachedPackages();
2308 ✗ files := PackageManagement.getInstalledLibraryVersions(str1);
2309 ✗ then
2310 ValuesMake.makeArray(List.map(files, ValuesMake.makeString));
2311
2312 case ("installPackage",{Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT(str1))), Values.STRING(str2), Values.BOOL(b)})
2313 algorithm
2314 ✗ (b, files) := PackageManagement.installPackage(str1, str2, b, wasmABI=CodegenWasmJitFunctions.prebuiltExternalsABI());
2315 ✗ CodegenWasmJitFunctions.precompilePrebuiltModules(files);
2316 ✗ then Values.BOOL(b);
2317
2318 case ("installPackage",{Values.CODE(Absyn.C_TYPENAME(path as Absyn.QUALIFIED())), _, _})
2319 algorithm
2320 ✗ Error.addMessage(Error.ERROR_PKG_NOT_IDENT, {AbsynUtil.pathString(path)});
2321 then
2322 Values.BOOL(false);
2323
2324 case ("installPackage",_)
2325 then Values.BOOL(false);
2326
2327 case ("updatePackageIndex",{})
2328 ✗ then Values.BOOL(PackageManagement.updateIndex());
2329
2330 case ("installWasmToolchain",{Values.BOOL(b)})
2331 ✗ then Values.STRING(PackageManagement.installWasmToolchain(b));
2332
2333 case ("upgradeInstalledPackages",{Values.BOOL(b)})
2334 ✗ then Values.BOOL(PackageManagement.upgradeInstalledPackages(b, wasmABI=CodegenWasmJitFunctions.prebuiltExternalsABI()));
2335
2336 case ("getAvailablePackageVersions",{Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT(str1))), Values.STRING(str2)})
2337 ✗ then ValuesMake.makeArray(list(ValuesMake.makeString(s) for s in PackageManagement.versionsThatProvideTheWanted(str1, str2, true)));
2338
2339 case ("getAvailablePackageVersions",_)
2340 ✗ then ValuesMake.makeArray({});
2341
2342 case ("getAvailablePackageConversionsFrom",{Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT(str1))), Values.STRING(str2)})
2343 ✗ then ValuesMake.makeStringArray(PackageManagement.versionsThatConvertFromTheWanted(str1, str2, true));
2344
2345 case ("getAvailablePackageConversionsFrom",_)
2346 ✗ then ValuesMake.makeArray({});
2347
2348 case ("getAvailablePackageConversionsTo",{Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT(str1))), Values.STRING(str2)})
2349 ✗ then ValuesMake.makeStringArray(PackageManagement.versionsThatConvertToTheWanted(str1, str2, true));
2350
2351 case ("getAvailablePackageConversionsTo",_)
2352 ✗ then ValuesMake.makeArray({});
2353
2354 case ("getUses",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2355 algorithm
2356 ✗ absynClass as Absyn.CLASS() := ProgramUtil.getPathedClassInProgram(classpath, SymbolTable.getAbsyn());
2357 ✗ uses := Interactive.getUsesAnnotation(Absyn.PROGRAM({absynClass},Absyn.TOP()));
2358 ✗ then
2359 ValuesMake.makeArray(List.map(uses,makeUsesArray));
2360
2361 case ("getConversionsFromVersions",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2362 algorithm
2363 ✗ absynClass as Absyn.CLASS() := ProgramUtil.getPathedClassInProgram(classpath, SymbolTable.getAbsyn());
2364 ✗ (withoutConversion,withConversion) := Interactive.getConversionAnnotation(absynClass);
2365 ✗ then
2366 Values.TUPLE({ValuesMake.makeArray(List.map(withoutConversion,ValuesMake.makeString)), ValuesMake.makeArray(List.map(withConversion,ValuesMake.makeString))});
2367
2368 case ("getDerivedClassModifierNames",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2369 algorithm
2370 ✗ absynClass := ProgramUtil.getPathedClassInProgram(classpath, SymbolTable.getAbsyn());
2371 ✗ args := Interactive.getDerivedClassModifierNames(absynClass);
2372 ✗ vals := List.map(args, ValuesMake.makeString);
2373 ✗ then
2374 ValuesMake.makeArray(vals);
2375
2376 case ("getDerivedClassModifierValue",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path))})
2377 algorithm
2378 2 absynClass := ProgramUtil.getPathedClassInProgram(classpath, SymbolTable.getAbsyn());
2379 ✗ str := Interactive.getDerivedClassModifierValue(absynClass, path);
2380 ✗ then
2381 Values.STRING(str);
2382
2383 case ("readSimulationResult",{Values.STRING(filename),Values.ARRAY(valueLst=cvars),Values.INTEGER(size)})
2384 algorithm
2385 52 vars_1 := List.map(cvars, ValuesUtil.printCodeVariableName);
2386 52 filename := Util.absoluteOrRelative(filename);
2387 52 then
2388 SimulationResults.readDataset(filename, vars_1, size);
2389
2390 case ("readSimulationResult",_)
2391 algorithm
2392 ✗ Error.addMessage(Error.SCRIPT_READ_SIM_RES_ERROR, {});
2393 then
2394 Values.META_FAIL();
2395
2396 case ("readSimulationResultSize",{Values.STRING(filename)})
2397 algorithm
2398 39 filename := Util.absoluteOrRelative(filename);
2399 39 i := SimulationResults.readSimulationResultSize(filename);
2400 39 then
2401 Values.INTEGER(i);
2402
2403 case ("readSimulationResultVars",{Values.STRING(filename),Values.BOOL(b1),Values.BOOL(b2)})
2404 algorithm
2405 7 filename := Util.absoluteOrRelative(filename);
2406 7 args := SimulationResults.readVariables(filename, b1, b2);
2407 7 vals := List.map(args, ValuesMake.makeString);
2408 7 then
2409 ValuesMake.makeArray(vals);
2410
2411 case ("compareSimulationResults",{Values.STRING(filename),Values.STRING(filename_1),Values.STRING(filename2),Values.REAL(x1),Values.REAL(x2),Values.ARRAY(valueLst=cvars)})
2412 algorithm
2413 183 Error.addMessage(Error.DEPRECATED_API_CALL, {"compareSimulationResults", "diffSimulationResults"});
2414 183 filename := Util.absoluteOrRelative(filename);
2415 183 filename_1 := Testsuite.friendlyPath(filename_1);
2416 183 filename_1 := Util.absoluteOrRelative(filename_1);
2417 183 filename2 := Util.absoluteOrRelative(filename2);
2418 183 vars_1 := List.map(cvars, ValuesUtil.extractValueString);
2419 183 strings := SimulationResults.cmpSimulationResults(Testsuite.isRunning(),filename,filename_1,filename2,x1,x2,vars_1);
2420 183 cvars := List.map(strings,ValuesMake.makeString);
2421 183 then
2422 ValuesMake.makeArray(cvars);
2423
2424 case ("compareSimulationResults",_)
2425 then Values.STRING("Error in compareSimulationResults");
2426
2427 case ("deltaSimulationResults",{Values.STRING(filename),Values.STRING(filename_1),Values.STRING(method_str),Values.ARRAY(valueLst=cvars)})
2428 algorithm
2429 12 filename := Util.absoluteOrRelative(filename);
2430 12 filename_1 := Testsuite.friendlyPath(filename_1);
2431 12 filename_1 := Util.absoluteOrRelative(filename_1);
2432 12 vars_1 := List.map(cvars, ValuesUtil.extractValueString);
2433 12 val := SimulationResults.deltaSimulationResults(filename,filename_1,method_str,vars_1);
2434 12 then
2435 Values.REAL(val);
2436
2437 case ("deltaSimulationResults",_)
2438 then Values.STRING("Error in deltaSimulationResults");
2439
2440 case ("filterSimulationResults",{Values.STRING(filename),Values.STRING(filename_1),Values.ARRAY(valueLst=cvars),Values.INTEGER(numberOfIntervals),Values.BOOL(b),Values.BOOL(hintReadAllVars)})
2441 algorithm
2442 3 vars_1 := List.map(cvars, ValuesUtil.extractValueString);
2443 3 b := SimulationResults.filterSimulationResults(filename,filename_1,vars_1,numberOfIntervals,b,hintReadAllVars=hintReadAllVars);
2444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 then
2445 Values.BOOL(b);
2446
2447 case ("filterSimulationResults",_)
2448 then Values.BOOL(false);
2449
2450 case ("diffSimulationResults",{Values.STRING(filename),Values.STRING(filename_1),Values.STRING(filename2),Values.REAL(reltol),Values.REAL(reltolDiffMinMax),Values.REAL(rangeDelta),Values.ARRAY(valueLst=cvars),Values.BOOL(b)})
2451 algorithm
2452 238 filename := Util.absoluteOrRelative(filename);
2453 238 filename_1 := Testsuite.friendlyPath(filename_1);
2454 238 filename_1 := Util.absoluteOrRelative(filename_1);
2455 238 filename2 := Util.absoluteOrRelative(filename2);
2456 238 vars_1 := List.map(cvars, ValuesUtil.extractValueString);
2457 238 (b,strings) := SimulationResults.diffSimulationResults(Testsuite.isRunning(),filename,filename_1,filename2,reltol,reltolDiffMinMax,rangeDelta,vars_1,b);
2458 238 cvars := List.map(strings,ValuesMake.makeString);
2459 238 v1 := ValuesMake.makeArray(cvars);
2460
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 235 times.
479 then
2461 Values.TUPLE({Values.BOOL(b),v1});
2462
2463 case ("diffSimulationResults",_)
2464 algorithm
2465 ✗ v := ValuesMake.makeArray({});
2466 ✗ then
2467 Values.TUPLE({Values.BOOL(false),v});
2468
2469 case ("diffSimulationResultsHtml",{Values.STRING(str),Values.STRING(filename),Values.STRING(filename_1),Values.REAL(reltol),Values.REAL(reltolDiffMinMax),Values.REAL(rangeDelta)})
2470 algorithm
2471 ✗ filename := Util.absoluteOrRelative(filename);
2472 ✗ filename_1 := Testsuite.friendlyPath(filename_1);
2473 ✗ filename_1 := Util.absoluteOrRelative(filename_1);
2474 ✗ str := SimulationResults.diffSimulationResultsHtml(Testsuite.isRunning(),filename,filename_1,reltol,reltolDiffMinMax,rangeDelta,str);
2475 ✗ then
2476 Values.STRING(str);
2477
2478 case ("diffSimulationResultsHtml",_)
2479 then Values.STRING("");
2480
2481 case ("checkTaskGraph",{Values.STRING(filename),Values.STRING(filename_1)})
2482 algorithm
2483 1 pwd := System.pwd();
2484 pd := Autoconf.pathDelimiter;
2485
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
2 filename := if StringUtil.startsWith(filename, "/") then filename else stringAppendList({pwd,pd,filename});
2486
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
2 filename_1 := if StringUtil.startsWith(filename_1, "/") then filename_1 else stringAppendList({pwd,pd,filename_1});
2487 1 strings := TaskGraphResults.checkTaskGraph(filename, filename_1);
2488 1 cvars := List.map(strings,ValuesMake.makeString);
2489 1 then
2490 ValuesMake.makeArray(cvars);
2491
2492 case ("checkTaskGraph",_)
2493 then Values.STRING("Error in checkTaskGraph");
2494
2495 case ("checkCodeGraph",{Values.STRING(filename),Values.STRING(filename_1)})
2496 algorithm
2497 ✗ pwd := System.pwd();
2498 pd := Autoconf.pathDelimiter;
2499 ✗ filename := if StringUtil.startsWith(filename, "/") then filename else stringAppendList({pwd,pd,filename});
2500 ✗ filename_1 := if StringUtil.startsWith(filename_1, "/") then filename_1 else stringAppendList({pwd,pd,filename_1});
2501 ✗ strings := TaskGraphResults.checkCodeGraph(filename, filename_1);
2502 ✗ cvars := List.map(strings,ValuesMake.makeString);
2503 ✗ then
2504 ValuesMake.makeArray(cvars);
2505
2506 case ("checkCodeGraph",_)
2507 then Values.STRING("Error in checkCodeGraph");
2508
2509 //plotAll(model)
2510 case ("plotAll",
2511 {
2512 Values.BOOL(externalWindow),
2513 Values.STRING(filename),
2514 Values.STRING(title),
2515 Values.STRING(gridStr),
2516 Values.BOOL(logX),
2517 Values.BOOL(logY),
2518 Values.STRING(xLabel),
2519 Values.STRING(yLabel),
2520 Values.ARRAY(valueLst={Values.REAL(x1),Values.REAL(x2)}),
2521 Values.ARRAY(valueLst={Values.REAL(y1),Values.REAL(y2)}),
2522 Values.REAL(curveWidth),
2523 Values.INTEGER(curveStyle),
2524 Values.STRING(legendPosition),
2525 Values.STRING(footer),
2526 Values.BOOL(autoScale),
2527 Values.BOOL(forceOMPlot),
2528 Values.STRING(yAxis),
2529 Values.STRING(yLabelRight),
2530 Values.ARRAY(valueLst={Values.REAL(y1R),Values.REAL(y2R)})
2531 })
2532 algorithm
2533 // get OPENMODELICAHOME
2534 ✗ omhome := Settings.getInstallationDirectoryPath();
2535 // get the simulation filename
2536 ✗ (outCache,filename) := cevalCurrentSimulationResultExp(outCache,inEnv,filename,msg);
2537 pd := Autoconf.pathDelimiter;
2538 // create absolute path of simulation result file
2539 ✗ str1 := System.pwd() + pd + filename;
2540 s1 := if Autoconf.os == "Windows_NT" then ".exe" else "";
2541 ✗ filename := if System.regularFileExists(str1) then str1 else filename;
2542 // check if plot callback is defined
2543 ✗ b := System.plotCallBackDefined();
2544 ✗ if boolOr(forceOMPlot, boolNot(b)) then
2545 // create the path till OMPlot
2546 ✗ str2 := stringAppendList({omhome,pd,"bin",pd,"OMPlot",s1});
2547 // create the list of arguments for OMPlot
2548 ✗ str3 := "--filename=\"" + filename + "\" --title=\"" + title + "\" --grid=" + gridStr + " --plotAll --logx=" + boolString(logX) + " --logy=" + boolString(logY) + " --yaxis=\"" + yAxis + "\" --xlabel=\"" + xLabel + "\" --ylabel=\"" + yLabel + "\" --ylabel-right=\"" + yLabelRight + "\" --xrange=" + realString(x1) + ":" + realString(x2) + " --yrange=" + realString(y1) + ":" + realString(y2) + " --yrange-right=" + realString(y1R) + ":" + realString(y2R) + " --new-window=" + boolString(externalWindow) + " --curve-width=" + realString(curveWidth) + " --curve-style=" + intString(curveStyle) + " --legend-position=\"" + legendPosition + "\" --footer=\"" + footer + "\" --auto-scale=" + boolString(autoScale);
2549 ✗ call := stringAppendList({"\"",str2,"\""," ",str3});
2550 ✗ 0 := System.spawnCall(str2, call);
2551 elseif b then
2552 ✗ logXStr := boolString(logX);
2553 ✗ logYStr := boolString(logY);
2554 ✗ x1Str := realString(x1);
2555 ✗ x2Str := realString(x2);
2556 ✗ y1Str := realString(y1);
2557 ✗ y2Str := realString(y2);
2558 ✗ curveWidthStr := realString(curveWidth);
2559 ✗ curveStyleStr := intString(curveStyle);
2560 ✗ autoScaleStr := boolString(autoScale);
2561 ✗ System.plotCallBack(externalWindow,filename,title,gridStr,"plotall",logXStr,logYStr,xLabel,yLabel,x1Str,x2Str,y1Str,y2Str,curveWidthStr,curveStyleStr,legendPosition,footer,autoScaleStr,"");
2562 end if;
2563 then
2564 Values.BOOL(true);
2565
2566 case ("plotAll",_)
2567 then Values.BOOL(false);
2568
2569 // plot(x, model)
2570 case ("plot",
2571 {
2572 Values.ARRAY(valueLst = cvars),
2573 Values.BOOL(externalWindow),
2574 Values.STRING(filename),
2575 Values.STRING(title),
2576 Values.STRING(gridStr),
2577 Values.BOOL(logX),
2578 Values.BOOL(logY),
2579 Values.STRING(xLabel),
2580 Values.STRING(yLabel),
2581 Values.ARRAY(valueLst={Values.REAL(x1),Values.REAL(x2)}),
2582 Values.ARRAY(valueLst={Values.REAL(y1),Values.REAL(y2)}),
2583 Values.REAL(curveWidth),
2584 Values.INTEGER(curveStyle),
2585 Values.STRING(legendPosition),
2586 Values.STRING(footer),
2587 Values.BOOL(autoScale),
2588 Values.BOOL(forceOMPlot),
2589 Values.STRING(yAxis),
2590 Values.STRING(yLabelRight),
2591 Values.ARRAY(valueLst={Values.REAL(y1R),Values.REAL(y2R)})
2592 })
2593 algorithm
2594 // get the variables list
2595 ✗ vars_1 := List.map(cvars, ValuesUtil.printCodeVariableName);
2596 // get OPENMODELICAHOME
2597 ✗ omhome := Settings.getInstallationDirectoryPath();
2598 // get the simulation filename
2599 ✗ (outCache,filename) := cevalCurrentSimulationResultExp(outCache,inEnv,filename,msg);
2600 pd := Autoconf.pathDelimiter;
2601 // create absolute path of simulation result file
2602 ✗ str1 := System.pwd() + pd + filename;
2603 s1 := if Autoconf.os == "Windows_NT" then ".exe" else "";
2604 ✗ filename := if System.regularFileExists(str1) then str1 else filename;
2605 // check if plot callback is defined
2606 ✗ b := System.plotCallBackDefined();
2607 ✗ if boolOr(forceOMPlot, boolNot(b)) then
2608 // seperate the variables
2609 ✗ str := stringDelimitList(vars_1,"' '");
2610 // create the path till OMPlot
2611 ✗ str2 := stringAppendList({omhome,pd,"bin",pd,"OMPlot",s1});
2612 // create the list of arguments for OMPlot
2613 ✗ str3 := "--filename=\"" + filename + "\" --title=\"" + title + "\" --grid=" + gridStr + " --plot --logx=" + boolString(logX) + " --logy=" + boolString(logY) + " --yaxis=\"" + yAxis + "\" --xlabel=\"" + xLabel + "\" --ylabel=\"" + yLabel + "\" --ylabel-right=\"" + yLabelRight + "\" --xrange=" + realString(x1) + ":" + realString(x2) + " --yrange=" + realString(y1) + ":" + realString(y2) + " --yrange-right=" + realString(y1R) + ":" + realString(y2R) + " --new-window=" + boolString(externalWindow) + " --curve-width=" + realString(curveWidth) + " --curve-style=" + intString(curveStyle) + " --legend-position=\"" + legendPosition + "\" --footer=\"" + footer + "\" --auto-scale=" + boolString(autoScale) + " '" + str + "'";
2614 ✗ call := stringAppendList({"\"",str2,"\""," ",str3});
2615 ✗ 0 := System.spawnCall(str2, call);
2616 elseif b then
2617 ✗ logXStr := boolString(logX);
2618 ✗ logYStr := boolString(logY);
2619 ✗ x1Str := realString(x1);
2620 ✗ x2Str := realString(x2);
2621 ✗ y1Str := realString(y1);
2622 ✗ y2Str := realString(y2);
2623 ✗ curveWidthStr := realString(curveWidth);
2624 ✗ curveStyleStr := intString(curveStyle);
2625 ✗ autoScaleStr := boolString(autoScale);
2626 // seperate the variables
2627 ✗ str := stringDelimitList(vars_1, " ");
2628 ✗ System.plotCallBack(externalWindow,filename,title,gridStr,"plot",logXStr,logYStr,xLabel,yLabel,x1Str,x2Str,y1Str,y2Str,curveWidthStr,curveStyleStr,legendPosition,footer,autoScaleStr,str);
2629 end if;
2630 then
2631 Values.BOOL(true);
2632
2633 case ("plot",_)
2634 then Values.BOOL(false);
2635
2636 case ("val",{cvar,Values.REAL(timeStamp),Values.STRING("<default>")})
2637 algorithm
2638
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2422 times.
2422 (outCache,Values.STRING(filename)) := Ceval.ceval(outCache,inEnv,buildCurrentSimulationResultExp(), true, msg, 0);
2639 2422 varNameStr := ValuesUtil.printCodeVariableName(cvar);
2640 2422 val := SimulationResults.val(filename,varNameStr,timeStamp);
2641 2422 then
2642 Values.REAL(val);
2643
2644 case ("val",{cvar,Values.REAL(timeStamp),Values.STRING(filename)})
2645 algorithm
2646
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
88 false := stringEq(filename,"<default>");
2647 88 varNameStr := ValuesUtil.printCodeVariableName(cvar);
2648 88 val := SimulationResults.val(filename,varNameStr,timeStamp);
2649 88 then
2650 Values.REAL(val);
2651
2652 case ("closeSimulationResultFile",_)
2653 algorithm
2654 4 SimulationResults.close();
2655 then
2656 Values.BOOL(true);
2657
2658 case ("getParameterNames",{Values.CODE(Absyn.C_TYPENAME(path))})
2659 algorithm
2660 ✗ strings := Interactive.getParameterNames(path, SymbolTable.getAbsyn());
2661 ✗ vals := List.map(strings, ValuesMake.makeString);
2662 ✗ then
2663 ValuesMake.makeArray(vals);
2664
2665 case ("getParameterValue",{Values.CODE(Absyn.C_TYPENAME(path)),Values.STRING(str1)})
2666 algorithm
2667 4 str2 := Interactive.getComponentBinding(path, str1, SymbolTable.getAbsyn());
2668 4 then
2669 Values.STRING(str2);
2670
2671 case ("setParameterValue", {Values.CODE(Absyn.C_TYPENAME(classpath)),
2672 Values.CODE(Absyn.C_TYPENAME(path)), Values.CODE(Absyn.C_EXPRESSION(aexp))})
2673 algorithm
2674 6 (p, b) := InteractiveUtil.setElementModifier(classpath, path,
2675 Absyn.Modification.CLASSMOD({}, Absyn.EqMod.EQMOD(aexp, Absyn.dummyInfo)), SymbolTable.getAbsyn());
2676 6 SymbolTable.setAbsyn(p);
2677 6 then
2678 ValuesMake.makeBoolean(b);
2679
2680 case ("getComponentModifierNames",{Values.CODE(Absyn.C_TYPENAME(path)),Values.STRING(str1)})
2681 algorithm
2682 13 strings := Interactive.getComponentModifierNames(path, str1, SymbolTable.getAbsyn());
2683 13 vals := List.map(strings, ValuesMake.makeString);
2684 13 then
2685 ValuesMake.makeArray(vals);
2686
2687 case ("getComponentModifierValue",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.CODE(Absyn.C_TYPENAME(path))})
2688 algorithm
2689 26 cr := AbsynUtil.pathToCref(path);
2690
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 22 times.
26 if AbsynUtil.crefIsIdent(cr) then
2691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 Absyn.CREF_IDENT(name = s1) := cr;
2692 4 str := Interactive.getComponentBinding(classpath, s1, SymbolTable.getAbsyn());
2693 else
2694 22 s1 := AbsynUtil.crefFirstIdent(cr);
2695 22 cr := AbsynUtil.crefStripFirst(cr);
2696 22 str := Interactive.getComponentModifierValue(AbsynUtil.pathToCref(classpath), Absyn.CREF_IDENT(s1, {}), cr, SymbolTable.getAbsyn());
2697 end if;
2698 26 then
2699 Values.STRING(str);
2700
2701 case ("getComponentModifierValues",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.CODE(Absyn.C_TYPENAME(path))})
2702 algorithm
2703 1 cr := AbsynUtil.pathToCref(path);
2704
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if AbsynUtil.crefIsIdent(cr) then
2705 ✗ Absyn.CREF_IDENT(name = s1) := cr;
2706 ✗ str := Interactive.getComponentBinding(classpath, s1, SymbolTable.getAbsyn());
2707 else
2708 1 s1 := AbsynUtil.crefFirstIdent(cr);
2709 1 cr := AbsynUtil.crefStripFirst(cr);
2710 1 str := Interactive.getComponentModifierValues(AbsynUtil.pathToCref(classpath), Absyn.CREF_IDENT(s1, {}), cr, SymbolTable.getAbsyn());
2711 end if;
2712 1 then
2713 Values.STRING(str);
2714
2715 case ("setElementModifierValue",
2716 {Values.CODE(Absyn.C_TYPENAME(classpath)),
2717 Values.CODE(Absyn.C_TYPENAME(path)),
2718 Values.CODE(Absyn.C_MODIFICATION(modification = mod))})
2719 algorithm
2720 42 (p, b) := InteractiveUtil.setElementModifier(classpath, path, mod, SymbolTable.getAbsyn());
2721
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 1 time.
42 if b then
2722 41 SymbolTable.setAbsynClass(p, ProgramUtil.getPathedClassInProgram(classpath, p), classpath);
2723 else
2724 1 SymbolTable.setAbsyn(p);
2725 end if;
2726
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 41 times.
43 then
2727 Values.BOOL(b);
2728
2729 case ("getExtendsModifierValue",
2730 {Values.CODE(Absyn.C_TYPENAME(classpath)),
2731 Values.CODE(Absyn.C_TYPENAME(baseClassPath)),
2732 Values.CODE(Absyn.C_TYPENAME(path))})
2733 12 then Interactive.getExtendsModifierValue(classpath, baseClassPath, path, SymbolTable.getAbsyn());
2734
2735 case ("setExtendsModifierValue",
2736 {Values.CODE(Absyn.C_TYPENAME(classpath)),
2737 Values.CODE(Absyn.C_TYPENAME(baseClassPath)),
2738 Values.CODE(Absyn.C_TYPENAME(path)),
2739 Values.CODE(Absyn.C_MODIFICATION(modification = mod))})
2740 algorithm
2741 9 (p, b) := InteractiveUtil.setExtendsModifier(classpath, baseClassPath, path, mod, SymbolTable.getAbsyn());
2742 9 SymbolTable.setAbsyn(p);
2743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 then
2744 Values.BOOL(b);
2745
2746 case ("setExtendsModifier",
2747 {Values.CODE(Absyn.C_TYPENAME(classpath)),
2748 Values.CODE(Absyn.C_TYPENAME(baseClassPath)),
2749 Values.CODE(Absyn.C_MODIFICATION(modification = mod))})
2750 algorithm
2751 1 (p, b) := InteractiveUtil.setExtendsModifier(classpath, baseClassPath, Absyn.Path.IDENT("_"), mod, SymbolTable.getAbsyn());
2752 1 SymbolTable.setAbsyn(p);
2753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
2754 Values.BOOL(b);
2755
2756 case ("isExtendsModifierFinal",
2757 {Values.CODE(Absyn.C_TYPENAME(classpath)),
2758 Values.CODE(Absyn.C_TYPENAME(baseClassPath)),
2759 Values.CODE(Absyn.C_TYPENAME(path))})
2760 4 then Interactive.isExtendsModifierFinal(classpath, baseClassPath, path, SymbolTable.getAbsyn());
2761
2762 case ("removeComponentModifiers",
2763 Values.CODE(Absyn.C_TYPENAME(path))::
2764 Values.STRING(str1)::
2765 Values.BOOL(keepRedeclares)::_)
2766 algorithm
2767 2 (p,b) := Interactive.removeComponentModifiers(path, str1, SymbolTable.getAbsyn(), keepRedeclares);
2768 2 SymbolTable.setAbsyn(p);
2769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 then
2770 Values.BOOL(b);
2771
2772 case ("getElementModifierNames",{Values.CODE(Absyn.C_TYPENAME(path)),Values.STRING(str1)})
2773 algorithm
2774 ✗ strings := InteractiveUtil.getElementModifierNames(path, str1, SymbolTable.getAbsyn());
2775 ✗ vals := List.map(strings, ValuesMake.makeString);
2776 ✗ then
2777 ValuesMake.makeArray(vals);
2778
2779 case ("getElementModifierValue",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.CODE(Absyn.C_TYPENAME(path))})
2780 algorithm
2781 ✗ cr := AbsynUtil.pathToCref(path);
2782 ✗ if AbsynUtil.crefIsIdent(cr) then
2783 ✗ Absyn.CREF_IDENT(name = s1) := cr;
2784 ✗ str := InteractiveUtil.getElementBinding(classpath, s1, SymbolTable.getAbsyn());
2785 else
2786 ✗ s1 := AbsynUtil.crefFirstIdent(cr);
2787 ✗ cr := AbsynUtil.crefStripFirst(cr);
2788 ✗ str := InteractiveUtil.getElementModifierValue(AbsynUtil.pathToCref(classpath), Absyn.CREF_IDENT(s1, {}), cr, SymbolTable.getAbsyn());
2789 end if;
2790 ✗ then
2791 Values.STRING(str);
2792
2793 case ("getElementModifierValues",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.CODE(Absyn.C_TYPENAME(path))})
2794 algorithm
2795 ✗ cr := AbsynUtil.pathToCref(path);
2796 ✗ if AbsynUtil.crefIsIdent(cr) then
2797 ✗ Absyn.CREF_IDENT(name = s1) := cr;
2798 ✗ str := InteractiveUtil.getElementBinding(classpath, s1, SymbolTable.getAbsyn());
2799 else
2800 ✗ s1 := AbsynUtil.crefFirstIdent(cr);
2801 ✗ cr := AbsynUtil.crefStripFirst(cr);
2802 ✗ str := InteractiveUtil.getElementModifierValues(AbsynUtil.pathToCref(classpath), Absyn.CREF_IDENT(s1, {}), cr, SymbolTable.getAbsyn());
2803 end if;
2804 ✗ then
2805 Values.STRING(str);
2806
2807 case ("removeElementModifiers",
2808 Values.CODE(Absyn.C_TYPENAME(path))::
2809 Values.STRING(str1)::
2810 Values.BOOL(keepRedeclares)::_)
2811 algorithm
2812 ✗ (p,b) := InteractiveUtil.removeElementModifiers(path, str1, SymbolTable.getAbsyn(), keepRedeclares);
2813 ✗ SymbolTable.setAbsyn(p);
2814 ✗ then
2815 Values.BOOL(b);
2816
2817 case ("removeExtendsModifiers",
2818 Values.CODE(Absyn.C_TYPENAME(classpath))::
2819 Values.CODE(Absyn.C_TYPENAME(baseClassPath))::
2820 Values.BOOL(keepRedeclares)::_)
2821 algorithm
2822 1 (p,b) := Interactive.removeExtendsModifiers(classpath, baseClassPath, SymbolTable.getAbsyn(), keepRedeclares);
2823 1 SymbolTable.setAbsyn(p);
2824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
2825 Values.BOOL(b);
2826
2827 case ("getInstantiatedParametersAndValues",{Values.CODE(Absyn.C_TYPENAME(classpath))})
2828 algorithm
2829 ✗ (outCache,_,odae) := runFrontEnd(outCache,inEnv,classpath,true);
2830 ✗ strings := Interactive.getInstantiatedParametersAndValues(odae);
2831 ✗ vals := List.map(strings, ValuesMake.makeString);
2832 ✗ then
2833 ValuesMake.makeArray(vals);
2834
2835 case ("getInstantiatedParametersAndValues",_)
2836 algorithm
2837 ✗ Error.addCompilerWarning("getInstantiatedParametersAndValues failed to instantiate the model.");
2838 ✗ then
2839 ValuesMake.makeArray({});
2840
2841 case ("updateConnection",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.STRING(str1), Values.STRING(str2),Values.CODE(Absyn.C_EXPRESSION(aexp))})
2842 algorithm
2843 2 p := InteractiveUtil.updateConnectionAnnotation(AbsynUtil.pathToCref(classpath), str1, str2, Absyn.NAMEDARG("annotate",aexp)::{}, SymbolTable.getAbsyn());
2844 1 SymbolTable.setAbsyn(p);
2845 then
2846 Values.BOOL(true);
2847
2848 case ("updateConnection",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.STRING(str1), Values.STRING(str2),
2849 Values.CODE(Absyn.C_MODIFICATION(Absyn.CLASSMOD(elementArgLst=annlst,eqMod=Absyn.NOMOD())))})
2850 algorithm
2851 1 p := SymbolTable.getAbsyn();
2852 1 absynClass := ProgramUtil.getPathedClassInProgram(classpath, p);
2853 1 absynClass := InteractiveUtil.updateConnectionAnnotationInClass(absynClass, str1, str2, Absyn.ANNOTATION(annlst));
2854
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 p := ProgramUtil.updateProgram(Absyn.PROGRAM({absynClass}, if AbsynUtil.pathIsIdent(classpath) then Absyn.TOP() else Absyn.WITHIN(AbsynUtil.stripLast(classpath))), p);
2855 1 SymbolTable.setAbsyn(p);
2856 then
2857 Values.BOOL(true);
2858
2859 case ("updateConnection",_) then Values.BOOL(false);
2860
2861 case ("updateConnectionAnnotation",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.STRING(str1), Values.STRING(str2),Values.STRING(annStr)})
2862 algorithm
2863 1 istmts := Parser.parsestringexp("__dummy(" + annStr + ");");
2864
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
1 GlobalScript.ISTMTS(interactiveStmtLst = {GlobalScript.IEXP(exp = aexp)}) := istmts;
2865
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 Absyn.CALL(functionArgs = Absyn.FUNCTIONARGS(argNames = nargs)) := aexp;
2866
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
1 Absyn.NAMEDARG(argValue = Absyn.CODE(Absyn.C_MODIFICATION(Absyn.CLASSMOD(elementArgLst=annlst,eqMod=Absyn.NOMOD())))) := listHead(nargs);
2867 1 p := SymbolTable.getAbsyn();
2868 1 absynClass := ProgramUtil.getPathedClassInProgram(classpath, p);
2869 1 absynClass := InteractiveUtil.updateConnectionAnnotationInClass(absynClass, str1, str2, Absyn.ANNOTATION(annlst));
2870
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 p := ProgramUtil.updateProgram(Absyn.PROGRAM({absynClass}, if AbsynUtil.pathIsIdent(classpath) then Absyn.TOP() else Absyn.WITHIN(AbsynUtil.stripLast(classpath))), p);
2871 1 SymbolTable.setAbsynClass(p, absynClass, classpath);
2872 then
2873 Values.BOOL(true);
2874
2875 case ("updateConnectionAnnotation",_) then Values.BOOL(false);
2876
2877 case ("updateConnectionNames",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.STRING(str1), Values.STRING(str2),
2878 Values.STRING(str3), Values.STRING(str4)})
2879 algorithm
2880 ✗ (b, p) := InteractiveUtil.updateConnectionNames(classpath, str1, str2, str3, str4, SymbolTable.getAbsyn());
2881 ✗ SymbolTable.setAbsyn(p);
2882 ✗ then
2883 Values.BOOL(b);
2884
2885 case ("updateConnectionNames",_) then Values.BOOL(false);
2886
2887 case ("getConnectionCount",{Values.CODE(Absyn.C_TYPENAME(path))})
2888 algorithm
2889 2 absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
2890 2 access := Interactive.checkAccessAnnotationAndEncryption(path, SymbolTable.getAbsyn());
2891
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if access >= Access.diagram then
2892 2 n := listLength(Interactive.getConnections(absynClass));
2893 else
2894 ✗ Error.addMessage(Error.ACCESS_ENCRYPTED_PROTECTED_CONTENTS, {});
2895 n := 0;
2896 end if;
2897 2 then
2898 Values.INTEGER(n);
2899
2900 case ("getConnectionCount",_) then Values.INTEGER(0);
2901
2902 case ("getNthConnection",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)})
2903 algorithm
2904 4 access := Interactive.checkAccessAnnotationAndEncryption(path, SymbolTable.getAbsyn());
2905
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if access >= Access.diagram then
2906 4 vals := Interactive.getNthConnection(AbsynUtil.pathToCref(path), SymbolTable.getAbsyn(), n);
2907 else
2908 ✗ Error.addMessage(Error.ACCESS_ENCRYPTED_PROTECTED_CONTENTS, {});
2909 vals := {};
2910 end if;
2911 4 then
2912 ValuesMake.makeArray(vals);
2913
2914 ✗ case ("getNthConnection",_) then ValuesMake.makeArray({});
2915
2916 case ("getConnectionList", {Values.CODE(Absyn.C_TYPENAME(path))})
2917 2 then getConnectionList(path);
2918
2919 case ("getAlgorithmCount",{Values.CODE(Absyn.C_TYPENAME(path))})
2920 algorithm
2921 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
2922 ✗ n := listLength(getAlgorithms(absynClass));
2923 ✗ then
2924 Values.INTEGER(n);
2925
2926 case ("getAlgorithmCount",_) then Values.INTEGER(0);
2927
2928 case ("getNthAlgorithm",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)})
2929 algorithm
2930 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
2931 ✗ str := getNthAlgorithm(absynClass, n);
2932 ✗ then
2933 Values.STRING(str);
2934
2935 case ("getNthAlgorithm",_) then Values.STRING("");
2936
2937 case ("getInitialAlgorithmCount",{Values.CODE(Absyn.C_TYPENAME(path))})
2938 algorithm
2939 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
2940 ✗ n := listLength(getInitialAlgorithms(absynClass));
2941 ✗ then
2942 Values.INTEGER(n);
2943
2944 case ("getInitialAlgorithmCount",_) then Values.INTEGER(0);
2945
2946 case ("getNthInitialAlgorithm",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)})
2947 algorithm
2948 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
2949 ✗ str := getNthInitialAlgorithm(absynClass, n);
2950 ✗ then
2951 Values.STRING(str);
2952
2953 case ("getNthInitialAlgorithm",_) then Values.STRING("");
2954
2955 case ("getAlgorithmItemsCount",{Values.CODE(Absyn.C_TYPENAME(path))})
2956 algorithm
2957 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
2958 ✗ n := getAlgorithmItemsCount(absynClass);
2959 ✗ then
2960 Values.INTEGER(n);
2961
2962 case ("getAlgorithmItemsCount",_) then Values.INTEGER(0);
2963
2964 case ("getNthAlgorithmItem",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)})
2965 algorithm
2966 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
2967 ✗ str := getNthAlgorithmItem(absynClass, n);
2968 ✗ then
2969 Values.STRING(str);
2970
2971 case ("getNthAlgorithmItem",_) then Values.STRING("");
2972
2973 case ("getInitialAlgorithmItemsCount",{Values.CODE(Absyn.C_TYPENAME(path))})
2974 algorithm
2975 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
2976 ✗ n := getInitialAlgorithmItemsCount(absynClass);
2977 ✗ then
2978 Values.INTEGER(n);
2979
2980 case ("getInitialAlgorithmItemsCount",_) then Values.INTEGER(0);
2981
2982 case ("getNthInitialAlgorithmItem",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)})
2983 algorithm
2984 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
2985 ✗ str := getNthInitialAlgorithmItem(absynClass, n);
2986 ✗ then
2987 Values.STRING(str);
2988
2989 case ("getNthInitialAlgorithmItem",_) then Values.STRING("");
2990
2991 case ("getEquationCount",{Values.CODE(Absyn.C_TYPENAME(path))})
2992 algorithm
2993 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
2994 ✗ n := listLength(getEquations(absynClass));
2995 ✗ then
2996 Values.INTEGER(n);
2997
2998 case ("getEquationCount",_) then Values.INTEGER(0);
2999
3000 case ("getNthEquation",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)})
3001 algorithm
3002 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
3003 ✗ str := getNthEquation(absynClass, n);
3004 ✗ then
3005 Values.STRING(str);
3006
3007 case ("getNthEquation",_) then Values.STRING("");
3008
3009 case ("getInitialEquationCount",{Values.CODE(Absyn.C_TYPENAME(path))})
3010 algorithm
3011 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
3012 ✗ n := listLength(getInitialEquations(absynClass));
3013 ✗ then
3014 Values.INTEGER(n);
3015
3016 case ("getInitialEquationCount",_) then Values.INTEGER(0);
3017
3018 case ("getNthInitialEquation",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)})
3019 algorithm
3020 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
3021 ✗ str := getNthInitialEquation(absynClass, n);
3022 ✗ then
3023 Values.STRING(str);
3024
3025 case ("getNthInitialEquation",_) then Values.STRING("");
3026
3027 case ("getEquationItemsCount",{Values.CODE(Absyn.C_TYPENAME(path))})
3028 algorithm
3029 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
3030 ✗ n := getEquationItemsCount(absynClass);
3031 ✗ then
3032 Values.INTEGER(n);
3033
3034 case ("getEquationItemsCount",_) then Values.INTEGER(0);
3035
3036 case ("getNthEquationItem",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)})
3037 algorithm
3038 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
3039 ✗ str := getNthEquationItem(absynClass, n);
3040 ✗ then
3041 Values.STRING(str);
3042
3043 case ("getNthEquationItem",_) then Values.STRING("");
3044
3045 case ("getInitialEquationItemsCount",{Values.CODE(Absyn.C_TYPENAME(path))})
3046 algorithm
3047 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
3048 ✗ n := getInitialEquationItemsCount(absynClass);
3049 ✗ then
3050 Values.INTEGER(n);
3051
3052 case ("getInitialEquationItemsCount",_) then Values.INTEGER(0);
3053
3054 case ("getNthInitialEquationItem",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)})
3055 algorithm
3056 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
3057 ✗ str := getNthInitialEquationItem(absynClass, n);
3058 ✗ then
3059 Values.STRING(str);
3060
3061 case ("getNthInitialEquationItem",_) then Values.STRING("");
3062
3063 case ("getAnnotationCount",{Values.CODE(Absyn.C_TYPENAME(path))})
3064 algorithm
3065 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
3066 ✗ n := getAnnotationCount(absynClass);
3067 ✗ then
3068 Values.INTEGER(n);
3069
3070 case ("getAnnotationCount",_) then Values.INTEGER(0);
3071
3072 case ("getNthAnnotationString",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)})
3073 algorithm
3074 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
3075 ✗ str := getNthAnnotationString(absynClass, n);
3076 ✗ then
3077 Values.STRING(str);
3078
3079 case ("getNthAnnotationString",_) then Values.STRING("");
3080
3081 case ("getImportCount",{Values.CODE(Absyn.C_TYPENAME(path))})
3082 algorithm
3083 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
3084 ✗ n := getImportCount(absynClass);
3085 ✗ then
3086 Values.INTEGER(n);
3087
3088 case ("getImportCount",_) then Values.INTEGER(0);
3089
3090 case ("getNthImport",{Values.CODE(Absyn.C_TYPENAME(path)),Values.INTEGER(n)})
3091 algorithm
3092 ✗ absynClass := ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn());
3093 ✗ vals := getNthImport(absynClass, n);
3094 ✗ then
3095 ValuesMake.makeArray(vals);
3096
3097 ✗ case ("getNthImport",_) then ValuesMake.makeArray({});
3098
3099 // plotParametric
3100 case ("plotParametric",
3101 {
3102 cvar,
3103 cvar2,
3104 Values.BOOL(externalWindow),
3105 Values.STRING(filename),
3106 Values.STRING(title),
3107 Values.STRING(gridStr),
3108 Values.BOOL(logX),
3109 Values.BOOL(logY),
3110 Values.STRING(xLabel),
3111 Values.STRING(yLabel),
3112 Values.ARRAY(valueLst={Values.REAL(x1),Values.REAL(x2)}),
3113 Values.ARRAY(valueLst={Values.REAL(y1),Values.REAL(y2)}),
3114 Values.REAL(curveWidth),
3115 Values.INTEGER(curveStyle),
3116 Values.STRING(legendPosition),
3117 Values.STRING(footer),
3118 Values.BOOL(autoScale),
3119 Values.BOOL(forceOMPlot),
3120 Values.STRING(yAxis),
3121 Values.STRING(yLabelRight),
3122 Values.ARRAY(valueLst={Values.REAL(y1R),Values.REAL(y2R)})
3123 })
3124 algorithm
3125 // get OPENMODELICAHOME
3126 ✗ omhome := Settings.getInstallationDirectoryPath();
3127 // get the simulation filename
3128 ✗ (outCache,filename) := cevalCurrentSimulationResultExp(outCache,inEnv,filename,msg);
3129 pd := Autoconf.pathDelimiter;
3130 // create absolute path of simulation result file
3131 ✗ str1 := System.pwd() + pd + filename;
3132 s1 := if Autoconf.os == "Windows_NT" then ".exe" else "";
3133 ✗ filename := if System.regularFileExists(str1) then str1 else filename;
3134 // check if plot callback is defined
3135 ✗ b := System.plotCallBackDefined();
3136 ✗ if boolOr(forceOMPlot, boolNot(b)) then
3137 // get the variables
3138 ✗ str := ValuesUtil.printCodeVariableName(cvar) + "\" \"" + ValuesUtil.printCodeVariableName(cvar2);
3139 // create the path till OMPlot
3140 ✗ str2 := stringAppendList({omhome,pd,"bin",pd,"OMPlot",s1});
3141 // create the list of arguments for OMPlot
3142 ✗ str3 := "--filename=\"" + filename + "\" --title=\"" + title + "\" --grid=" + gridStr + " --plotParametric --logx=" + boolString(logX) + " --logy=" + boolString(logY) + " --yaxis=\"" + yAxis + "\" --xlabel=\"" + xLabel + "\" --ylabel=\"" + yLabel + "\" --ylabel-right=\"" + yLabelRight + "\" --xrange=" + realString(x1) + ":" + realString(x2) + " --yrange=" + realString(y1) + ":" + realString(y2) + " --yrange-right=" + realString(y1R) + ":" + realString(y2R) + " --new-window=" + boolString(externalWindow) + " --curve-width=" + realString(curveWidth) + " --curve-style=" + intString(curveStyle) + " --legend-position=\"" + legendPosition + "\" --footer=\"" + footer + "\" --auto-scale=" + boolString(autoScale) + " \"" + str + "\"";
3143 ✗ call := stringAppendList({"\"",str2,"\""," ",str3});
3144 ✗ 0 := System.spawnCall(str2, call);
3145 elseif b then
3146 // get the variables
3147 ✗ str := ValuesUtil.printCodeVariableName(cvar) + " " + ValuesUtil.printCodeVariableName(cvar2);
3148 ✗ logXStr := boolString(logX);
3149 ✗ logYStr := boolString(logY);
3150 ✗ x1Str := realString(x1);
3151 ✗ x2Str := realString(x2);
3152 ✗ y1Str := realString(y1);
3153 ✗ y2Str := realString(y2);
3154 ✗ curveWidthStr := realString(curveWidth);
3155 ✗ curveStyleStr := intString(curveStyle);
3156 ✗ autoScaleStr := boolString(autoScale);
3157 ✗ System.plotCallBack(externalWindow,filename,title,gridStr,"plotparametric",logXStr,logYStr,xLabel,yLabel,x1Str,x2Str,y1Str,y2Str,curveWidthStr,curveStyleStr,legendPosition,footer,autoScaleStr,str);
3158 end if;
3159 then
3160 Values.BOOL(true);
3161
3162 case ("plotParametric",_)
3163 then Values.BOOL(false);
3164
3165 case ("dumpXMLDAE",vals)
3166 algorithm
3167 2 (outCache,xml_filename) := dumpXMLDAE(outCache,inEnv,vals, msg);
3168 4 then
3169 ValuesMake.makeTuple({Values.BOOL(true),Values.STRING(xml_filename)});
3170
3171 case ("dumpXMLDAE",_)
3172 ✗ then
3173 ValuesMake.makeTuple({Values.BOOL(false),Values.STRING("")});
3174
3175 case ("solveLinearSystem",{Values.ARRAY(valueLst=vals),v})
3176 algorithm
3177 ✗ (realVals,i) := System.dgesv(List.map(vals,ValuesUtil.arrayValueReals),ValuesUtil.arrayValueReals(v));
3178 ✗ v := ValuesMake.makeArray(List.map(realVals,ValuesMake.makeReal));
3179 ✗ then
3180 Values.TUPLE({v,Values.INTEGER(i)});
3181
3182 case ("solveLinearSystem",{_,v,_,_})
3183 algorithm
3184 ✗ Error.addMessage(Error.INTERNAL_ERROR,{"Unknown input to solveLinearSystem scripting function"});
3185 ✗ then
3186 Values.TUPLE({v,Values.INTEGER(-1)});
3187
3188 case ("relocateFunctions",{Values.STRING(str), v as Values.ARRAY()})
3189 algorithm
3190 relocatableFunctionsTuple := {};
3191 ✗ for varr in v.valueLst loop
3192 ✗ Values.ARRAY(valueLst={Values.STRING(s1),Values.STRING(s2)}) := varr;
3193 ✗ relocatableFunctionsTuple := (s1,s2)::relocatableFunctionsTuple;
3194 end for;
3195 ✗ b := System.relocateFunctions(str, relocatableFunctionsTuple);
3196 ✗ then
3197 Values.BOOL(b);
3198
3199 case ("toJulia",{})
3200 algorithm
3201 ✗ str := Tpl.tplString(AbsynToJulia.dumpProgram, SymbolTable.getAbsyn());
3202 ✗ then
3203 Values.STRING(str);
3204
3205 case ("interactiveDumpAbsynToJL",{})
3206 algorithm
3207 ✗ str := Tpl.tplString(AbsynJLDumpTpl.dump, SymbolTable.getAbsyn());
3208 ✗ then
3209 Values.STRING(str);
3210
3211 case ("relocateFunctions",_) then Values.BOOL(false);
3212
3213 case ("runConversionScript", {Values.CODE(Absyn.C_TYPENAME(path)), Values.STRING(str)})
3214 9 then runConversionScript(path, str);
3215
3216 case ("convertPackageToLibrary", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path)), Values.STRING(str)})
3217 2 then convertPackageToLibrary(classpath, path, str);
3218
3219 case ("getModelInstance", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path)), Values.STRING(str), Values.BOOL(b)})
3220 48 then NFApi.getModelInstance(classpath, path, str, b);
3221
3222 case ("getModelInstanceAnnotation", {Values.CODE(Absyn.C_TYPENAME(classpath)), v as Values.ARRAY(), Values.BOOL(b)})
3223 3 then NFApi.getModelInstanceAnnotation(classpath, ValuesUtil.arrayValueStrings(v), b);
3224
3225 case ("getModelInstanceReference", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path)), Values.STRING(str)})
3226 ✗ then NFApi.getModelInstanceReference(classpath, path, str);
3227
3228 case ("getModelInstanceAnnotationReference", {Values.CODE(Absyn.C_TYPENAME(classpath)), v as Values.ARRAY()})
3229 ✗ then NFApi.getModelInstanceAnnotationReference(classpath, ValuesUtil.arrayValueStrings(v));
3230
3231 case ("releaseModelInstanceReference", {Values.INTEGER(i)})
3232 ✗ then NFApi.releaseModelInstanceReference(i);
3233
3234 case ("modifierToJSON", {Values.STRING(str), Values.BOOL(b)})
3235 ✗ then NFApi.modifierToJSON(str, b);
3236
3237 case ("storeAST", {})
3238 ✗ then Values.INTEGER(SymbolTable.storeAST());
3239
3240 case ("restoreAST", {Values.INTEGER(integer = n)})
3241 ✗ then Values.BOOL(SymbolTable.restoreAST(n));
3242
3243 case ("qualifyPath", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path))})
3244 1 then ValuesMake.makeCodeTypeName(NFApi.mkFullyQual(SymbolTable.getAbsyn(), classpath, path));
3245
3246 case ("getElementAnnotation", {Values.CODE(Absyn.C_TYPENAME(path))})
3247 4 then Values.STRING(InteractiveUtil.getElementAnnotation(path, SymbolTable.getAbsyn()));
3248
3249 case ("setElementAnnotation",
3250 {Values.CODE(Absyn.C_TYPENAME(path)),
3251 Values.CODE(Absyn.C_MODIFICATION(modification = mod))})
3252 algorithm
3253 ✗ (_, b) := InteractiveUtil.setElementAnnotation(path, mod, SymbolTable.getAbsyn());
3254 ✗ then
3255 Values.BOOL(b);
3256
3257 case ("loadClassContentString",
3258 {Values.STRING(str), Values.CODE(Absyn.C_TYPENAME(classpath)), Values.INTEGER(x), Values.INTEGER(y)})
3259 algorithm
3260 1 (p, b) := InteractiveUtil.loadClassContentString(str, classpath, x, y, SymbolTable.getAbsyn());
3261 1 SymbolTable.setAbsyn(p);
3262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
3263 Values.BOOL(b);
3264
3265 case ("setElementType",
3266 {Values.CODE(Absyn.C_TYPENAME(path)),
3267 Values.CODE(Absyn.C_VARIABLENAME(cr))})
3268 algorithm
3269 ✗ (_, b) := InteractiveUtil.setElementType(path, cr, SymbolTable.getAbsyn());
3270 ✗ then
3271 Values.BOOL(b);
3272
3273 case ("getExtendsModifierNames",
3274 {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path)), Values.BOOL(b)})
3275 11 then InteractiveUtil.getExtendsModifierNames(classpath, path, b, SymbolTable.getAbsyn());
3276
3277 case ("isPrimitive", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3278 2 then ValuesMake.makeBoolean(Interactive.isPrimitive(classpath, SymbolTable.getAbsyn()));
3279
3280 case ("isParameter", {Values.CODE(Absyn.C_TYPENAME(path)), Values.CODE(Absyn.C_TYPENAME(classpath))})
3281 ✗ then ValuesMake.makeBoolean(Interactive.isParameter(path, classpath, SymbolTable.getAbsyn()));
3282
3283 case ("isConstant", {Values.CODE(Absyn.C_TYPENAME(path)), Values.CODE(Absyn.C_TYPENAME(classpath))})
3284 ✗ then ValuesMake.makeBoolean(Interactive.isConstant(path, classpath, SymbolTable.getAbsyn()));
3285
3286 case ("isProtected", {Values.CODE(Absyn.C_TYPENAME(path)), Values.CODE(Absyn.C_TYPENAME(classpath))})
3287 ✗ then ValuesMake.makeBoolean(Interactive.isProtected(path, classpath, SymbolTable.getAbsyn()));
3288
3289 case ("setComponentDimensions", {Values.CODE(Absyn.C_TYPENAME(classpath)),
3290 Values.CODE(Absyn.C_TYPENAME(path)), Values.CODE(Absyn.C_EXPRESSION(aexp as Absyn.Exp.ARRAY()))})
3291 algorithm
3292 ✗ (p, b) := Interactive.setComponentDimensions(classpath, path, aexp.arrayExp, SymbolTable.getAbsyn());
3293 ✗ SymbolTable.setAbsyn(p);
3294 ✗ then
3295 ValuesMake.makeBoolean(b);
3296
3297 case ("setComponentProperties", {Values.CODE(Absyn.C_TYPENAME(classpath)),
3298 Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT(name))),
3299 Values.ARRAY(valueLst = vals),
3300 Values.ARRAY(valueLst = {Values.STRING(s1)}),
3301 Values.ARRAY(valueLst = {Values.BOOL(b1), Values.BOOL(b2)}),
3302 Values.ARRAY(valueLst = {Values.STRING(s2)})})
3303 algorithm
3304
6/6
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 12 times.
✓ Branch 5 taken 24 times.
✓ Branch 6 taken 28 times.
64 (p, v) := Interactive.setComponentProperties(classpath, name,
3305 list(ValuesUtil.valueBool(va) for va in vals), s1, b1, b2, s2, SymbolTable.getAbsyn());
3306 12 SymbolTable.setAbsyn(p);
3307 12 then
3308 v;
3309
3310 case ("createModel", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3311 algorithm
3312 8 p := Interactive.createModel(classpath, SymbolTable.getAbsyn());
3313 8 SymbolTable.setAbsyn(p);
3314 8 then
3315 ValuesMake.makeBoolean(true);
3316
3317 case ("newModel", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path))})
3318 algorithm
3319 ✗ p := Interactive.newModel(classpath, path, SymbolTable.getAbsyn());
3320 ✗ SymbolTable.setAbsyn(p);
3321 ✗ then
3322 ValuesMake.makeBoolean(true);
3323
3324 case ("deleteClass", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3325 algorithm
3326 4 (b, p) := Interactive.deleteClass(classpath, SymbolTable.getAbsyn());
3327 4 SymbolTable.setAbsynDeleted(p, classpath);
3328 4 then
3329 ValuesMake.makeBoolean(b);
3330
3331 case ("addComponent", {Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT(name))),
3332 Values.CODE(Absyn.C_TYPENAME(path)), Values.CODE(Absyn.C_TYPENAME(classpath)),
3333 Values.CODE(Absyn.C_EXPRESSION(aexp)), Values.CODE(Absyn.C_MODIFICATION(modification = mod)),
3334 Values.CODE(Absyn.C_EXPRESSION(aexp2)), Values.CODE(Absyn.C_EXPRESSION(aexp3))})
3335 algorithm
3336 18 (p, b) := Interactive.addComponent(name, path, classpath, aexp, mod, aexp2, aexp3, SymbolTable.getAbsyn());
3337 18 SymbolTable.setAbsyn(p);
3338 18 then
3339 ValuesMake.makeBoolean(b);
3340
3341 case ("updateComponent", {Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT(name))),
3342 Values.CODE(Absyn.C_TYPENAME(path)), Values.CODE(Absyn.C_TYPENAME(classpath)),
3343 Values.CODE(Absyn.C_EXPRESSION(aexp)), Values.CODE(Absyn.C_MODIFICATION(modification = mod)),
3344 Values.CODE(Absyn.C_EXPRESSION(aexp2)), Values.CODE(Absyn.C_EXPRESSION(aexp3))})
3345 algorithm
3346 5 (p, b) := Interactive.updateComponent(name, path, classpath, aexp, mod, aexp2, aexp3, SymbolTable.getAbsyn());
3347 5 SymbolTable.setAbsyn(p);
3348 5 then
3349 ValuesMake.makeBoolean(b);
3350
3351 case ("deleteComponent", {Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT(name))), Values.CODE(Absyn.C_TYPENAME(classpath))})
3352 algorithm
3353 ✗ (p, b) := Interactive.deleteComponent(name, classpath, SymbolTable.getAbsyn());
3354 ✗ SymbolTable.setAbsyn(p);
3355 ✗ then
3356 ValuesMake.makeBoolean(b);
3357
3358 case ("getComponentCount", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3359 5 then ValuesMake.makeInteger(Interactive.getComponentCount(classpath, SymbolTable.getAbsyn()));
3360
3361 case ("getNthComponent", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.INTEGER(n)})
3362 2 then Interactive.getNthComponent(classpath, SymbolTable.getAbsyn(), n);
3363
3364 case ("getComponents", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.BOOL(b)})
3365 20 then Interactive.getComponents(classpath, b, SymbolTable.getAbsyn());
3366
3367 case ("getElements", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.BOOL(b)})
3368 2 then Interactive.getElements(classpath, b, SymbolTable.getAbsyn());
3369
3370 case ("getElementsInfo", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3371 6 then Interactive.getElementsInfo(classpath, SymbolTable.getAbsyn());
3372
3373 case ("getComponentAnnotations", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3374 5 then Interactive.getComponentAnnotations(classpath, SymbolTable.getAbsyn());
3375
3376 case ("getElementAnnotations", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3377 2 then Interactive.getElementAnnotations(classpath, SymbolTable.getAbsyn());
3378
3379 case ("getNthComponentAnnotation", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.INTEGER(n)})
3380 3 then Interactive.getNthComponentAnnotation(classpath, n, SymbolTable.getAbsyn());
3381
3382 case ("getNthComponentModification", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.INTEGER(n)})
3383 ✗ then Interactive.getNthComponentModification(classpath, n, SymbolTable.getAbsyn());
3384
3385 case ("getNthComponentCondition", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.INTEGER(n)})
3386 ✗ then Interactive.getNthComponentCondition(classpath, n, SymbolTable.getAbsyn());
3387
3388 case ("getInheritanceCount", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3389 2 then Interactive.getInheritanceCount(classpath, SymbolTable.getAbsyn());
3390
3391 case ("getNthInheritedClass", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.INTEGER(n)})
3392 3 then NFApi.getNthInheritedClass(classpath, n, SymbolTable.getAbsyn());
3393
3394 case ("setConnectionComment", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_VARIABLENAME(cr)),
3395 Values.CODE(Absyn.C_VARIABLENAME(cr2)), Values.STRING(str)})
3396 algorithm
3397 2 (p, b) := Interactive.setConnectionComment(classpath, cr, cr2, str, SymbolTable.getAbsyn());
3398 2 SymbolTable.setAbsyn(p);
3399 2 then
3400 ValuesMake.makeBoolean(b);
3401
3402 case ("addConnection", {Values.CODE(Absyn.C_VARIABLENAME(cr)), Values.CODE(Absyn.C_VARIABLENAME(cr2)),
3403 Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_EXPRESSION(aexp)),
3404 Values.CODE(Absyn.C_EXPRESSION(aexp2))})
3405 algorithm
3406 6 (p, b) := Interactive.addConnection(classpath, cr, cr2, aexp, aexp2, SymbolTable.getAbsyn());
3407 6 SymbolTable.setAbsyn(p);
3408 6 then
3409 ValuesMake.makeBoolean(b);
3410
3411 case ("deleteConnection", {Values.CODE(Absyn.C_VARIABLENAME(cr)), Values.CODE(Absyn.C_VARIABLENAME(cr2)),
3412 Values.CODE(Absyn.C_TYPENAME(classpath))})
3413 algorithm
3414 ✗ (p, b) := Interactive.deleteConnection(classpath, cr, cr2, SymbolTable.getAbsyn());
3415 ✗ SymbolTable.setAbsyn(p);
3416 ✗ then
3417 ValuesMake.makeBoolean(b);
3418
3419 case ("getNthConnectionAnnotation", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.INTEGER(n)})
3420 2 then Interactive.getNthConnectionAnnotation(classpath, n, SymbolTable.getAbsyn());
3421
3422 case ("getConnectorCount", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3423 2 then Interactive.getConnectorCount(classpath, SymbolTable.getAbsyn());
3424
3425 case ("getNthConnector", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.INTEGER(n)})
3426 ✗ then Interactive.getNthConnector(classpath, n, SymbolTable.getAbsyn());
3427
3428 case ("getNthConnectorIconAnnotation", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.INTEGER(n)})
3429 1 then Interactive.getNthConnectorIconAnnotation(classpath, n, SymbolTable.getAbsyn());
3430
3431 case ("getIconAnnotation", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3432 16 then Interactive.getIconAnnotation(classpath, SymbolTable.getAbsyn());
3433
3434 case ("getDiagramAnnotation", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3435 4 then Interactive.getDiagramAnnotation(classpath, SymbolTable.getAbsyn());
3436
3437 case ("refactorIconAnnotation", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3438 ✗ then Interactive.refactorIconAnnotation(classpath, SymbolTable.getAbsyn());
3439
3440 case ("refactorDiagramAnnotation", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3441 ✗ then Interactive.refactorDiagramAnnotation(classpath, SymbolTable.getAbsyn());
3442
3443 case ("refactorClass", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3444 1 then Interactive.refactorClass(classpath, SymbolTable.getAbsyn());
3445
3446 case ("getNthInheritedClassIconMapAnnotation", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.INTEGER(n)})
3447 ✗ then Interactive.getNthInheritedClassIconMapAnnotation(classpath, n, SymbolTable.getAbsyn());
3448
3449 case ("getNthInheritedClassDiagramMapAnnotation", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.INTEGER(n)})
3450 ✗ then Interactive.getNthInheritedClassDiagramMapAnnotation(classpath, n, SymbolTable.getAbsyn());
3451
3452 case ("getNamedAnnotation",
3453 {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path))})
3454 ✗ then Interactive.getNamedAnnotation(classpath, path, SymbolTable.getAbsyn());
3455
3456 case ("getShortDefinitionBaseClassInformation", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3457 ✗ then Interactive.getShortDefinitionBaseClassInformation(classpath, SymbolTable.getAbsyn());
3458
3459 case ("getExternalFunctionSpecification", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3460 ✗ then Interactive.getExternalFunctionSpecification(classpath, SymbolTable.getAbsyn());
3461
3462 case ("getEnumerationLiterals", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3463 ✗ then Interactive.getEnumerationLiterals(classpath, SymbolTable.getAbsyn());
3464
3465 case ("existClass", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3466 ✗ then ValuesMake.makeBoolean(Interactive.existClass(classpath, SymbolTable.getAbsyn()));
3467
3468 case ("getComponentComment", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path))})
3469 ✗ then Interactive.getComponentComment(classpath, path, SymbolTable.getAbsyn());
3470
3471 case ("setComponentComment", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path)), Values.STRING(str)})
3472 algorithm
3473 2 (p, b) := Interactive.setComponentComment(classpath, path, str, SymbolTable.getAbsyn());
3474 2 SymbolTable.setAbsyn(p);
3475 2 then
3476 ValuesMake.makeBoolean(b);
3477
3478 case ("renameClass", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path))})
3479 algorithm
3480 ✗ (p, v) := Interactive.renameClass(classpath, path, SymbolTable.getAbsyn());
3481 ✗ SymbolTable.setAbsyn(p);
3482 ✗ then
3483 v;
3484
3485 case ("renameComponent", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_VARIABLENAME(cr)),
3486 Values.CODE(Absyn.C_VARIABLENAME(cr2))})
3487 algorithm
3488 ✗ (p, v) := Interactive.renameComponent(classpath, cr, cr2, SymbolTable.getAbsyn());
3489 ✗ SymbolTable.setAbsyn(p);
3490 ✗ then
3491 v;
3492
3493 case ("renameComponentInClass", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_VARIABLENAME(cr)),
3494 Values.CODE(Absyn.C_VARIABLENAME(cr2))})
3495 algorithm
3496 ✗ (p, v) := Interactive.renameComponentOnlyInClass(classpath, cr, cr2, SymbolTable.getAbsyn());
3497 ✗ SymbolTable.setAbsyn(p);
3498 ✗ then
3499 v;
3500
3501 case ("getCrefInfo", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3502 7 then Interactive.getCrefInfo(classpath, SymbolTable.getAbsyn());
3503
3504 case ("getDefaultComponentName", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3505 2 then Interactive.getDefaultComponentName(classpath, SymbolTable.getAbsyn());
3506
3507 case ("getDefaultComponentPrefixes", {Values.CODE(Absyn.C_TYPENAME(classpath))})
3508 4 then Interactive.getDefaultComponentPrefixes(classpath, SymbolTable.getAbsyn());
3509
3510 case ("getDefinitions", {Values.BOOL(b)})
3511 ✗ then Interactive.getDefinitions(SymbolTable.getAbsyn(), b);
3512
3513 case ("getDefaultOpenCLDevice", {})
3514 ✗ then ValuesMake.makeInteger(Config.getDefaultOpenCLDevice());
3515
3516 case ("getDefUseChains", {Values.CODE(Absyn.C_TYPENAME(path)), Values.STRING(str), Values.CODE(Absyn.C_TYPENAME(classpath)), Values.BOOL(b)})
3517 18 then ValuesMake.makeString(getDefUseChains(path, str, classpath, b));
3518
3519 case ("getDependencyGraph", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(str), Values.BOOL(b)})
3520 3 then ValuesMake.makeString(getDependencyGraph(classpath, str, b));
3521
3522 case ("getDefinitionAt", {Values.STRING(str), Values.INTEGER(x), Values.INTEGER(y), Values.BOOL(b)})
3523 11 then ValuesMake.makeString(getDefinitionAt(str, x, y, b));
3524
3525 case ("getClassDiagram", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(str), Values.STRING(str1),
3526 Values.INTEGER(i), v as Values.ARRAY(), Values.BOOL(b)})
3527 7 then ValuesMake.makeString(getClassDiagram(classpath, str, str1, i, ValuesUtil.arrayValueStrings(v), b));
3528
3529 case ("reverseLookup", {Values.CODE(Absyn.C_TYPENAME(path)), Values.CODE(Absyn.C_TYPENAME(classpath)), Values.BOOL(b1), Values.BOOL(b2)})
3530 2 then ValuesMake.makeString(ReverseLookup.lookup(path, classpath, SymbolTable.getAbsyn(), b1, b2));
3531
3532 case ("translateResidualsDAE", {Values.CODE(Absyn.C_TYPENAME(path)), Values.STRING(s1)})
3533 ✗ then ValuesMake.makeBoolean(NFApi.translateResidualsDAE(path, s1));
3534
3535 case ("addEquation", {Values.CODE(Absyn.C_TYPENAME(path)), Values.STRING(s1), Values.BOOL(b1)})
3536 4 then ValuesMake.makeBoolean(Interactive.addEquation(path, s1, b1));
3537
3538 case ("updateEquation", {Values.CODE(Absyn.C_TYPENAME(path)), Values.STRING(s1), Values.STRING(s2), Values.BOOL(b), Values.BOOL(b1), Values.BOOL(b2), Values.BOOL(b3)})
3539 10 then ValuesMake.makeBoolean(Interactive.updateEquation(path, s1, s2, b, b1, b2, b3));
3540
3541 end matchcontinue;
3542 end cevalInteractiveFunctions4;
3543
3544 protected function getSimulationExtension
3545 input String inString;
3546 input String inString2;
3547 output String outString;
3548 algorithm
3549 outString:=match(inString,inString2)
3550 local
3551 // We now use a bat script, even for the C runtime, on Windows.
3552 case ("C","WIN64")
3553 then ".bat";
3554 case ("C","WIN32")
3555 then ".bat";
3556 case ("Cpp","WIN32")
3557 then ".bat";
3558 case ("Cpp","WIN64")
3559 then ".bat";
3560 case ("Cpp","Unix")
3561 then ".sh";
3562 else Autoconf.exeExt;
3563 end match;
3564 end getSimulationExtension;
3565
3566 public function getAdjacencyMatrix " author: adrpo
3567 translates a model and returns the adjacency matrix"
3568 input FCore.Cache inCache;
3569 input FCore.Graph inEnv;
3570 input Absyn.Path className "path for the model";
3571 input Absyn.Msg inMsg;
3572 input String filenameprefix;
3573 output FCore.Cache outCache;
3574 output Values.Value outValue;
3575 output String outString;
3576 algorithm
3577 (outCache,outValue,outString):=
3578 match (inCache, inEnv)
3579 local
3580 String filename,file_dir, str;
3581 DAE.DAElist dae;
3582 FCore.Graph env;
3583 BackendDAE.BackendDAE dlow;
3584 Absyn.ComponentRef a_cref;
3585 FCore.Cache cache;
3586 String flatModelicaStr,description;
3587
3588 case (cache, env) /* mo file directory */
3589 algorithm
3590 ✗ (cache, env, SOME(dae), _) := runFrontEnd(cache, env, className, true, transform = true);
3591 ✗ description := DAEUtil.daeDescription(dae);
3592 ✗ a_cref := AbsynUtil.pathToCref(className);
3593 ✗ file_dir := ProgramUtil.getFileDir(a_cref, SymbolTable.getAbsyn());
3594 ✗ dlow := BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix,NONE()));
3595 ✗ dlow := FindZeroCrossings.findZeroCrossings(dlow);
3596 ✗ flatModelicaStr := DAEDump.dumpStr(dae,FCore.getFunctionTree(cache));
3597 ✗ flatModelicaStr := stringAppend("OldEqStr={'", flatModelicaStr);
3598 ✗ flatModelicaStr := System.stringReplace(flatModelicaStr, "\n", "%##%");
3599 ✗ flatModelicaStr := System.stringReplace(flatModelicaStr, "%##%", "','");
3600 ✗ flatModelicaStr := stringAppend(flatModelicaStr,"'};");
3601 ✗ filename := DAEQuery.writeAdjacencyMatrix(dlow, filenameprefix, flatModelicaStr);
3602 ✗ str := stringAppend("The equation system was dumped to Matlab file:", filename);
3603 ✗ then
3604 (cache,Values.STRING(str),file_dir);
3605 end match;
3606 end getAdjacencyMatrix;
3607
3608 /* -------------------------------------------------------------------
3609 RUN FRONTEND
3610 ------------------------------------------------------------------- */
3611 public function runFrontEnd
3612 input output FCore.Cache cache;
3613 input output FCore.Graph env;
3614 input Absyn.Path className;
3615 input Boolean relaxedFrontEnd "Do not check for illegal simulation models, so we allow instantation of packages, etc";
3616 input Boolean dumpFlat = false;
3617 input Boolean transform = false;
3618 output Option<DAE.DAElist> odae = NONE();
3619 output String flatString = "";
3620 protected
3621 DAE.DAElist dae;
3622 Boolean b;
3623 algorithm
3624 // add program to the cache so it can be used to lookup modelica://
3625 // URIs in external functions IncludeDirectory/LibraryDirectory
3626 2523 FlagsUtil.setConfigBool(Flags.BUILDING_MODEL, true);
3627 try
3628 2523 b := loadProgram(className);
3629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2523 times.
2523 true := b;
3630
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2523 times.
2523 if Flags.isSet(Flags.GC_PROF) then
3631 ✗ print(GCExt.profStatsStr(GCExt.getProfStats(), head="GC stats before front-end:") + "\n");
3632 end if;
3633 2523 ExecStat.execStat("FrontEnd - loaded program");
3634 2523 (cache,env,dae,flatString) := runFrontEndWork(cache,env,className,relaxedFrontEnd,dumpFlat);
3635
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2213 times.
2213 if Flags.isSet(Flags.GC_PROF) then
3636 ✗ print(GCExt.profStatsStr(GCExt.getProfStats(), head="GC stats after front-end:") + "\n");
3637 end if;
3638 2213 ExecStat.execStat("FrontEnd - DAE generated");
3639
3640
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2211 times.
2213 if transform then
3641 2 dae := DAEUtil.transformationsBeforeBackend(cache, env, dae, StateMachineFlatten.stateMachineToDataFlow);
3642 end if;
3643
3644 2213 odae := SOME(dae);
3645 else
3646 // Return odae=NONE(); needed to update cache and symbol table if we fail
3647 end try;
3648 2523 FlagsUtil.setConfigBool(Flags.BUILDING_MODEL, false);
3649 end runFrontEnd;
3650
3651 public function runFrontEndNF
3652 input Absyn.Path className;
3653 input Boolean relaxedFrontEnd = false;
3654 input Boolean dumpFlat = false;
3655 output NFFlatModel flatModel;
3656 output NFFlatten.FunctionTree functions;
3657 output String flatString;
3658 algorithm
3659 ✗ true := loadProgram(className);
3660 ✗ (flatModel, functions, flatString) := runFrontEndWorkNF(className, relaxedFrontEnd, dumpFlat);
3661 end runFrontEndNF;
3662
3663 protected function loadProgram
3664 input Absyn.Path className;
3665 output Boolean success;
3666 protected
3667 String lib_name;
3668 Absyn.Program p;
3669 Boolean b;
3670 algorithm
3671 8903 p := SymbolTable.getAbsyn();
3672 8903 lib_name := AbsynUtil.pathFirstIdent(className);
3673
3674 try
3675 8903 ProgramUtil.getClassInProgram(lib_name, p);
3676 success := true;
3677 else
3678 ✗ (p,b) := CevalScript.loadModel({(Absyn.IDENT(lib_name),"the given model name to instantiate",{"default"},false)},Settings.getModelicaPath(Testsuite.isRunning()),p,true,true,true,false);
3679 ✗ Error.assertionOrAddSourceMessage(not b,Error.NOTIFY_IMPLICIT_LOAD,{lib_name,"default"},Absyn.dummyInfo);
3680 ✗ System.loadModelCallBack(lib_name);
3681 ✗ SymbolTable.setAbsyn(p);
3682 // Always update the SCode structure; otherwise the cache plays tricks on us
3683 ✗ SymbolTable.clearSCode();
3684 success := true;
3685 end try;
3686 end loadProgram;
3687
3688 protected function runFrontEndWork
3689 input output FCore.Cache cache;
3690 input output FCore.Graph env;
3691 input Absyn.Path className;
3692 input Boolean relaxedFrontEnd "Do not check for illegal simulation models, so we allow instantation of packages, etc";
3693 input Boolean dumpFlat;
3694 output DAE.DAElist dae;
3695 output String flatString = "";
3696 protected
3697 Integer numError = Error.getNumErrorMessages();
3698 Boolean graph_inst, nf_inst, nf_inst_actual;
3699 SCode.Program scodeP;
3700 AvlTreePathFunction.Tree funcs;
3701 NFFlatModel flat_model;
3702 NFFlatten.FunctionTree nf_funcs;
3703 algorithm
3704 2523 graph_inst := Flags.isSet(Flags.GRAPH_INST);
3705 2523 nf_inst := Flags.isSet(Flags.SCODE_INST);
3706 2523 nf_inst_actual := nf_inst;
3707
3708 // PDEModelica is not yet supported by the new frontend, switch to the old one
3709 // if `-g=PDEModelica` is set.
3710
4/4
✓ Branch 0 taken 1434 times.
✓ Branch 1 taken 1089 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1433 times.
2523 if nf_inst and Flags.getConfigEnum(Flags.GRAMMAR) == Flags.PDEMODELICA then
3711 nf_inst := false;
3712 1 FlagsUtil.set(Flags.SCODE_INST, false);
3713 1 Error.addMessage(Error.NF_PDE_NOT_IMPLEMENTED, {});
3714 end if;
3715
3716 (cache,env,dae) := matchcontinue (graph_inst, nf_inst)
3717 case (false, true)
3718 algorithm
3719 1433 (flat_model, nf_funcs, flatString) := runFrontEndWorkNF(className, relaxedFrontEnd, dumpFlat);
3720 1227 (dae, funcs) := NFConvertDAE.convert(flat_model, nf_funcs);
3721
3722 1227 cache := FCore.emptyCache();
3723 1227 FCore.setCachedFunctionTree(cache, funcs);
3724 1227 env := FGraph.new("graph", FCore.dummyTopModel);
3725 1227 then
3726 (cache, env, dae);
3727
3728 case (true, false)
3729 algorithm
3730 ✗ System.realtimeTick(ClockIndexes.RT_CLOCK_FINST);
3731 ✗ dae := FInst.instPath(className, SymbolTable.getSCode());
3732 ✗ then
3733 (cache,env,dae);
3734
3735 case (false, false)
3736 algorithm
3737 1090 scodeP := SymbolTable.getSCode();
3738 1090 ExecStat.execStat("FrontEnd - Absyn->SCode");
3739
3740 1090 (cache,env,_,dae) := Inst.instantiateClass(cache,InnerOuter.emptyInstHierarchy,scodeP,className,true,relaxedFrontEnd);
3741 986 dae := DAEUtil.mergeAlgorithmSections(dae);
3742
3743 // adrpo: do not add it to the instantiated classes, it just consumes memory for nothing.
3744 986 DAEUtil.getFunctionList(FCore.getFunctionTree(cache),failOnError=true); // Make sure that the functions are valid before returning success
3745 986 then (cache,env,dae);
3746
3747 case (_, _)
3748 guard Error.getNumErrorMessages() == numError
3749 algorithm
3750 // A user cancel unwinds with its message rolled back by the failed
3751 // speculation above; re-emit it here (the accepted branch) so it is not
3752 // masked by the generic "no error message" below.
3753 ✗ Error.checkCancel();
3754 ✗ Error.addMessage(Error.INTERNAL_ERROR,
3755 {"Instantiation of " + AbsynUtil.pathString(className) + " failed with no error message."});
3756 ✗ FlagsUtil.set(Flags.SCODE_INST, nf_inst_actual);
3757 ✗ then
3758 fail();
3759 end matchcontinue;
3760
3761 // Switch back to the new frontend in case we changed it at the beginning of the function.
3762 2213 FlagsUtil.set(Flags.SCODE_INST, nf_inst_actual);
3763 end runFrontEndWork;
3764
3765 public function runFrontEndWorkNF
3766 input Absyn.Path className;
3767 input Boolean relaxedFrontend = false;
3768 input Boolean dumpFlat = false;
3769 output NFFlatModel flatModel;
3770 output NFFlatten.FunctionTree functions;
3771 output String flatString;
3772 protected
3773 SCode.Program builtin_p, scode_p, annotation_p;
3774 Boolean nf_api;
3775 Absyn.Path cls_name = className;
3776 Obfuscate.Mapping obfuscate_map;
3777 String obfuscate_mode;
3778 algorithm
3779 1637 (_, builtin_p) := FBuiltin.getInitialFunctions();
3780 1637 scode_p := SymbolTable.getSCode();
3781
3782 1637 obfuscate_mode := Flags.getConfigString(Flags.OBFUSCATE);
3783
3784 // Enable obfuscation of encrypted variables if a higher obfuscation hasn't
3785 // been chosen and the AST contains encrypted classes.
3786
5/6
✓ Branch 0 taken 1636 times.
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 1635 times.
✓ Branch 4 taken 1 time.
✗ Branch 7 not taken.
✓ Branch 8 taken 1635 times.
1637 if obfuscate_mode == "none" and Interactive.astContainsEncryptedClass(SymbolTable.getAbsyn()) then
3787 ✗ FlagsUtil.setConfigString(Flags.OBFUSCATE, "encrypted");
3788 end if;
3789
3790
4/4
✓ Branch 0 taken 1636 times.
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1635 times.
1637 if obfuscate_mode == "full" then
3791 1 (scode_p, cls_name, _, _, obfuscate_map) := Obfuscate.obfuscateProgram(scode_p, cls_name);
3792 end if;
3793
3794 1637 scode_p := listAppend(builtin_p, scode_p);
3795 1637 ExecStat.execStat("FrontEnd - Absyn->SCode");
3796
3797 1637 annotation_p := AbsynToSCode.translateAbsyn2SCode(
3798 InteractiveUtil.modelicaAnnotationProgram(Config.getAnnotationVersion()));
3799
3800 // make sure we don't run the default instantiateModel using -d=nfAPI
3801 // only the stuff going via NFApi.mo should have this flag activated
3802 1637 nf_api := FlagsUtil.set(Flags.NF_API, false);
3803
3804 try
3805 1637 (flatModel, functions, flatString) :=
3806 NFInst.instClassInProgram(cls_name, scode_p, annotation_p, relaxedFrontend, dumpFlat);
3807 else
3808 207 NFInst.clearCaches();
3809 207 FlagsUtil.set(Flags.NF_API, nf_api);
3810 207 fail();
3811 end try;
3812
3813 1430 FlagsUtil.set(Flags.NF_API, nf_api);
3814 end runFrontEndWorkNF;
3815
3816 public function translateModel
3817 input FCore.Cache cache;
3818 input FCore.Graph env;
3819 input Absyn.Path className "path for the model";
3820 input String fileNamePrefix;
3821 input Boolean runBackend "if true, run the backend as well. This will run SimCode and Codegen as well.";
3822 input Boolean runSilent "if true, flat modelica code will not be dumped to out stream";
3823 input Option<SimCode.SimulationSettings> simSettingsOpt;
3824 output Boolean success;
3825 output FCore.Cache outCache;
3826 output list<String> outLibs;
3827 output String outFileDir;
3828 output list<tuple<String,Values.Value>> resultValues;
3829 protected
3830 Flags.Flag flags;
3831 InteractiveTypes.SimulationOptions defaultSimOpt;
3832 Option<SimCode.SimulationSettings> simSettings;
3833 algorithm
3834
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2446 times.
✓ Branch 2 taken 1262 times.
✓ Branch 3 taken 1184 times.
2446 if isSome(simSettingsOpt) then
3835 simSettings := simSettingsOpt;
3836 else
3837 1262 defaultSimOpt := buildSimulationOptionsFromModelExperimentAnnotation(className, fileNamePrefix, SOME(defaultSimulationOptions));
3838 1262 simSettings := SOME(convertSimulationOptionsToSimCode(defaultSimOpt));
3839 end if;
3840
3841 2446 flags := loadCommandLineOptionsFromModel(className);
3842 2446 CodegenWasmJitFunctions.precompilePrebuiltModules(PackageManagement.installMissingWasmOfLoaded(loadedClassFiles(), CodegenWasmJitFunctions.prebuiltExternalsABI()));
3843
3844 try
3845 2446 (success, outCache, outLibs, outFileDir, resultValues) :=
3846 SimCodeMain.translateModel(SimCodeMain.TranslateModelKind.NORMAL(), cache, env, className, fileNamePrefix,
3847 runBackend, Flags.getConfigBool(Flags.DAE_MODE), runSilent, simSettings, Absyn.FUNCTIONARGS({},{}));
3848 // reset to the original flags
3849 2135 FlagsUtil.saveFlags(flags);
3850 else
3851 311 FlagsUtil.saveFlags(flags);
3852 311 fail();
3853 end try;
3854 end translateModel;
3855
3856 protected function loadedClassFiles
3857 output list<String> files;
3858 protected
3859 Absyn.Program p = SymbolTable.getAbsyn();
3860 algorithm
3861
4/4
✓ Branch 0 taken 5443 times.
✓ Branch 1 taken 2446 times.
✓ Branch 2 taken 5443 times.
✓ Branch 3 taken 2446 times.
7889 files := list(AbsynUtil.classFilename(c) for c in p.classes);
3862 end loadedClassFiles;
3863
3864 protected function getProcsStr
3865 input Boolean isMake = false;
3866 output String s;
3867 protected
3868 Integer n;
3869 String sn;
3870 algorithm
3871 81 n := Flags.getConfigInt(Flags.NUM_PROC);
3872 81 sn := intString(n);
3873
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
81 s := if (n == 0)
3874 then ""
3875 else (if isMake
3876 then sn
3877 else stringAppend("-j", sn));
3878 end getProcsStr;
3879
3880 protected function configureFMU_cmake
3881 "Configure and build binaries with CMake for target platform"
3882 input String platform;
3883 input String fmutmp;
3884 input String fmuTargetName;
3885 input String logfile;
3886 input list<String> externalLibLocations;
3887 input Boolean isWindows;
3888 input Boolean needs3rdPartyLibs;
3889 protected
3890 String fmuSourceDir;
3891 String CMAKE_GENERATOR = "", CMAKE_BUILD_TYPE;
3892 String quote, dquote, defaultFmiIncludeDirectoy;
3893 String CC;
3894 SimCodeFunction.MakefileParams makefileParams;
3895 String msvcEnv, rmrf;
3896 algorithm
3897 81 makefileParams := SimCodeFunctionUtil.createMakefileParams({}, {}, {}, false, true);
3898 81 fmuSourceDir := fmutmp+"/sources/";
3899 quote := "'";
3900
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 dquote := if isWindows then "\"" else "'";
3901 81 msvcEnv := SimCodeUtil.msvcEnvironment();
3902
2/4
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 81 times.
✗ Branch 4 not taken.
81 if msvcEnv <> "" then
3903 // cmake picks cl from the Visual Studio environment.
3904 CC := "";
3905 CMAKE_GENERATOR := "-G \"NMake Makefiles\" ";
3906 rmrf := "rmdir /S /Q ";
3907 else
3908 81 CC := "-DCMAKE_C_COMPILER=" + dquote + System.basename(makefileParams.ccompiler) + dquote;
3909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 if isWindows then
3910 ✗ CMAKE_GENERATOR := "-G " + dquote + "MSYS Makefiles" + dquote + " ";
3911 end if;
3912 rmrf := "rm -rf ";
3913 end if;
3914 81 defaultFmiIncludeDirectoy := dquote + Settings.getInstallationDirectoryPath() + "/include/omc/c/fmi" + dquote;
3915
3916 // Set build type
3917
4/4
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 79 times.
81 if Flags.getConfigEnum(Flags.FMI_FILTER) == Flags.FMI_BLACKBOX or Flags.getConfigEnum(Flags.FMI_FILTER) == Flags.FMI_PROTECTED then
3918 CMAKE_BUILD_TYPE := "-DCMAKE_BUILD_TYPE=Release";
3919 elseif Flags.isSet(Flags.GEN_DEBUG_SYMBOLS) then
3920 CMAKE_BUILD_TYPE := "-DCMAKE_BUILD_TYPE=Debug";
3921 else
3922 CMAKE_BUILD_TYPE := "-DCMAKE_BUILD_TYPE=RelWithDebInfo";
3923 end if;
3924
3925 // Remove old log file
3926
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 81 times.
81 if System.regularFileExists(logfile) then
3927 ✗ System.removeFile(logfile);
3928 end if;
3929
3930 () := match Util.stringSplitAtChar(platform, " ")
3931 local
3932 String cmd;
3933 String cmakeCall;
3934 String crossTriple, buildDir, fmiTarget;
3935 String externalIncludeDirsFile;
3936 list<String> dockerImgArgs;
3937 ContainerImage.ContainerImage dockerImage;
3938 list<String> dockerArguments;
3939 String dockerRunArgs;
3940 Boolean isTrustedImage;
3941 Integer uid;
3942 String cidFile, volumeID, containerID, userID;
3943 String dockerLogFile;
3944 String cmake_toolchain;
3945 list<String> locations;
3946 case {"dynamic"}
3947 algorithm
3948 buildDir := "build_cmake_dynamic";
3949 2 cmakeCall := Autoconf.cmake + " " + CMAKE_GENERATOR +
3950 CMAKE_BUILD_TYPE + " " + CC +
3951 " ..";
3952 2 cmd := msvcEnv + "cd " + dquote + fmuSourceDir + dquote + " && " +
3953 "mkdir " + buildDir + " && cd " + buildDir + " && " +
3954 cmakeCall + " && " +
3955 Autoconf.cmake + " --build . --parallel " + getProcsStr() + " --target install && " +
3956 "cd .. && " + rmrf + buildDir;
3957
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if 0 <> System.systemCallRestrictedEnv(cmd, outFile=logfile) then
3958 ✗ Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {"cmd: " + cmd + "\n" + System.readFile(logfile)});
3959 ✗ fail();
3960 end if;
3961 then();
3962 case {"static"}
3963 algorithm
3964 buildDir := "build_cmake_static";
3965 79 cmakeCall := Autoconf.cmake + " " + CMAKE_GENERATOR +
3966 CMAKE_BUILD_TYPE + " " + CC +
3967 " ..";
3968 79 cmd := msvcEnv + "cd " + dquote + fmuSourceDir + dquote + " && " +
3969 "mkdir " + buildDir + " && cd " + buildDir + " && " +
3970 cmakeCall + " && " +
3971 Autoconf.cmake + " --build . --parallel " + getProcsStr() + " --target install && " +
3972 "cd .. && " + rmrf + buildDir;
3973
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
79 if 0 <> System.systemCallRestrictedEnv(cmd, outFile=logfile) then
3974 ✗ Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {"cmd: " + cmd + "\n" + System.readFile(logfile)});
3975 ✗ fail();
3976 end if;
3977 then();
3978 case crossTriple::"docker"::"run"::dockerImgArgs
3979 algorithm
3980 ✗ (dockerImage, dockerArguments) := ContainerImage.parseWithArgs(dockerImgArgs);
3981 ✗ dockerImage := ContainerImage.getDigestSha(dockerImage);
3982 ✗ Error.addCompilerNotification("Using docker image '" + ContainerImage.toString(dockerImage) + "' for cross compilation.");
3983 ✗ (_, isTrustedImage) := ContainerImage.isTrustedOpenModelicaImage(dockerImage);
3984 ✗ dockerRunArgs := stringDelimitList(dockerArguments, " ") + " " + ContainerImage.toString(dockerImage);
3985
3986 ✗ uid := System.getuid();
3987 ✗ cidFile := fmutmp+".cidfile";
3988
3989 // Temp log file outside of Docker volume
3990 ✗ dockerLogFile := crossTriple + ".tmp.log";
3991 // Remove old log file
3992 ✗ if System.regularFileExists(dockerLogFile) then
3993 ✗ System.removeFile(dockerLogFile);
3994 end if;
3995
3996 // Only download trusted images automatically, and only if the signature
3997 // can be verified. Images that are already on this machine are used as is.
3998 ✗ if isTrustedImage and not ContainerImage.isAvailableLocally(dockerImage) then
3999 ✗ if ContainerImage.isCosignAvailable() then
4000 // Verify the image in the registry first, it's only downloaded if the signature is valid.
4001 ✗ ContainerImage.assertSignature(dockerImage);
4002 ✗ ContainerImage.pull(dockerImage);
4003 else
4004 ✗ Error.addCompilerError("Refusing to download container image '" + ContainerImage.toString(dockerImage) + "' without verifying its signature.");
4005 ✗ Error.addCompilerNotification("Download the image manually with `" + ContainerImage.pullCommand(dockerImage) + "` and run the FMU export again.");
4006 ✗ fail();
4007 end if;
4008 end if;
4009
4010 // Create a docker volume for the FMU since we can't forward volumes
4011 // to the docker run command depending on where the FMU was generated (inside another volume)
4012 cmd := "docker volume create";
4013 ✗ runDockerCmd(cmd, dockerLogFile);
4014 ✗ volumeID := List.last(System.strtok(System.readFile(dockerLogFile), "\n"));
4015
4016 ✗ if System.regularFileExists(cidFile) then
4017 ✗ System.removeFile(cidFile);
4018 end if;
4019 ✗ cmd := "docker run --cidfile " + cidFile + " -v " + volumeID + ":/data busybox true";
4020 ✗ runDockerCmd(cmd, dockerLogFile, true, volumeID, "");
4021
4022 ✗ containerID := System.trim(System.readFile(cidFile));
4023 ✗ System.removeFile(cidFile);
4024
4025 // Copy the FMU contents to the container
4026 ✗ cmd := "docker cp " + fmutmp + " " + containerID + ":/data";
4027 ✗ runDockerCmd(cmd, dockerLogFile, cleanup=true, volumeID=volumeID, containerID=containerID);
4028
4029 // Copy the FMI headers to the container
4030 ✗ cmd := "docker cp " + defaultFmiIncludeDirectoy + " " + containerID + ":/data/fmiInclude";
4031 ✗ runDockerCmd(cmd, dockerLogFile, cleanup=true, volumeID=volumeID, containerID=containerID);
4032
4033 // Copy the external library and include files to the container
4034 ✗ (locations,_) := SimCodeUtil.getDirectoriesForDLLsFromLinkLibs(externalLibLocations);
4035 // SimCodeMain noted the external include directories of the model next to the
4036 // generated sources. Without them the cross compiler can't find the headers of
4037 // external libraries. See https://github.com/OpenModelica/OpenModelica/issues/9509
4038 ✗ externalIncludeDirsFile := fmutmp + "/.external_include_dirs";
4039 ✗ if System.regularFileExists(externalIncludeDirsFile) then
4040 ✗ locations := listAppend(System.strtok(System.readFile(externalIncludeDirsFile), "\n"), locations);
4041 end if;
4042 // CVODE_DIRECTORY is not one of the model's link directories, so nothing would
4043 // copy it for a model that has no external libraries of its own.
4044 ✗ if needs3rdPartyLibs then
4045 ✗ locations := Settings.getInstallationDirectoryPath() + "/lib/" + Autoconf.triple + "/omc" :: locations;
4046 end if;
4047 ✗ for loc in locations loop
4048 ✗ if System.directoryExists(loc) then
4049 // Create path
4050 ✗ cmd := "docker run --rm --hostname=" + containerID + " --volume=" + volumeID + ":/data busybox mkdir -p " + dquote + "/data" + loc + dquote;
4051 ✗ runDockerCmd(cmd, dockerLogFile, cleanup=true, volumeID=volumeID, containerID=containerID);
4052 // Copy files
4053 ✗ cmd := "docker cp -a -L " + dquote + loc + dquote + " " + containerID + dquote + ":/data" + System.dirname(loc) + dquote;
4054 ✗ runDockerCmd(cmd, dockerLogFile, cleanup=true, volumeID=volumeID, containerID=containerID);
4055 end if;
4056 end for;
4057
4058 // Build for target host
4059 ✗ userID := (if uid<>0 then "--user " + String(uid) else "");
4060 ✗ buildDir := "build_cmake_" + crossTriple;
4061 ✗ if 0 <> System.regex(crossTriple, "mingw", 1) then
4062 fmiTarget := " -DCMAKE_SYSTEM_NAME=Windows ";
4063 elseif 0 <> System.regex(crossTriple, "apple", 1) then
4064 fmiTarget := " -DCMAKE_SYSTEM_NAME=Darwin ";
4065 else
4066 fmiTarget := "";
4067 end if;
4068
4069 ✗ if isTrustedImage then
4070 ✗ cmake_toolchain := "-DCMAKE_TOOLCHAIN_FILE=/opt/cmake/toolchain/" + crossTriple + ".cmake ";
4071 else
4072 cmake_toolchain := "";
4073 end if;
4074
4075 ✗ cmakeCall := "cmake " + cmake_toolchain +
4076 "-DFMI_INTERFACE_HEADER_FILES_DIRECTORY=/fmu/fmiInclude " +
4077 "-DDOCKER_VOL_DIR=/fmu " +
4078 fmiTarget +
4079 CMAKE_BUILD_TYPE +
4080 " ..";
4081 ✗ cmd := "docker run " + userID + " --rm -w /fmu -v " + volumeID + ":/fmu " + dockerRunArgs +
4082 " sh -c " + dquote +
4083 "cd " + dquote + "/fmu/" + fmuSourceDir + dquote + " && " +
4084 "mkdir " + buildDir + " && cd " + buildDir + " && " +
4085 cmakeCall + " && " +
4086 "cmake --build . --parallel " + getProcsStr() + " --target install && " +
4087 "cd .. && rm -rf " + buildDir +
4088 dquote;
4089 ✗ runDockerCmd(cmd, dockerLogFile, cleanup=true, volumeID=volumeID, containerID=containerID);
4090
4091 // Copy the files back from the volume (via the container) to the filesystem.
4092 // Docker cp can't handle too long names on Windows.
4093 // Workaround: Zip it in the container, copy it to host, unzip it
4094 ✗ if isWindows then
4095 ✗ cmd := "docker run " + userID + " --rm -w /fmu -v " + volumeID + ":/fmu " + dockerRunArgs +
4096 " tar -zcf comp-fmutmp.tar.gz " + fmutmp;
4097 ✗ runDockerCmd(cmd, dockerLogFile, cleanup=true, volumeID=volumeID, containerID=containerID);
4098
4099 ✗ cmd := "docker cp " + containerID + ":/data/comp-fmutmp.tar.gz .";
4100 ✗ runDockerCmd(cmd, dockerLogFile, cleanup=true, volumeID=volumeID, containerID=containerID);
4101 ✗ if 0 <> System.systemCall("tar zxf comp-fmutmp.tar.gz && rm comp-fmutmp.tar.gz", outFile=dockerLogFile) then
4102 // Otherwise the failure only surfaces later as "Build commands returned
4103 // success, but <name>.fmu does not exist".
4104 ✗ Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {"Failed to unpack comp-fmutmp.tar.gz:\n" + System.readFile(dockerLogFile)});
4105 ✗ fail();
4106 end if;
4107 else
4108 ✗ cmd := "docker cp " + containerID + ":/data/" + fmutmp + "/ .";
4109 ✗ runDockerCmd(cmd, dockerLogFile, cleanup=false, volumeID=volumeID, containerID=containerID);
4110 end if;
4111
4112 // Cleanup
4113 ✗ System.systemCall("docker rm " + containerID, outFile=dockerLogFile);
4114 ✗ System.systemCall("docker volume rm " + volumeID, outFile=dockerLogFile);
4115
4116 // Copy log file into resources directory
4117 ✗ System.copyFile(dockerLogFile, logfile);
4118 ✗ System.removeFile(dockerLogFile);
4119 then();
4120 else
4121 algorithm
4122 ✗ Error.addMessage(Error.SIMULATOR_BUILD_ERROR,
4123 {"Unknown/unsupported platform \"" + platform + " \" for CMake FMU build. " +
4124 "Use platforms={\"dynamic\"} for the default case."});
4125 ✗ then fail();
4126 end match;
4127 end configureFMU_cmake;
4128
4129 protected function runDockerCmd
4130 "Run a docker command. Can clean up volumen and container on failure."
4131 input String cmd;
4132 input String logfile;
4133 input Boolean cleanup = false;
4134 input String volumeID = "";
4135 input String containerID = "";
4136 protected
4137 Boolean verbose = false;
4138 algorithm
4139 ✗ System.appendFile(logfile, cmd + "\n");
4140 ✗ if 0 <> System.systemCall(cmd, outFile=logfile) then
4141 ✗ Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {cmd + " failed:\n" + System.readFile(logfile)});
4142
4143 ✗ if cleanup then
4144 ✗ if not stringEqual(containerID, "") then
4145 ✗ System.systemCall("docker rm " + containerID, outFile=logfile);
4146 end if;
4147 ✗ if not stringEqual(volumeID, "") then
4148 ✗ System.systemCall("docker volume rm " + volumeID, outFile=logfile);
4149 end if;
4150 end if;
4151
4152 ✗ fail();
4153 elseif verbose then
4154 print(System.readFile(logfile) +"\n");
4155 end if;
4156 end runDockerCmd;
4157
4158 protected function isDockerPlatform
4159 input String platform;
4160 output Boolean isDocker;
4161 algorithm
4162 isDocker := match Util.stringSplitAtChar(platform, " ")
4163 case _::"docker"::"run"::_ then true;
4164 else false;
4165 end match;
4166 end isDockerPlatform;
4167
4168 protected function translateModelFMU
4169 "translates modelica model as FMU, generates only c code and does not build"
4170 input FCore.Cache inCache;
4171 input FCore.Graph inEnv;
4172 input Absyn.Path className "path for the model";
4173 input String FMUVersion;
4174 input String inFMUType;
4175 input String inFileNamePrefix;
4176 input Boolean addDummy "if true, add a dummy state";
4177 input list<String> platforms = {"static"};
4178 input Option<SimCode.SimulationSettings> inSimSettings = NONE();
4179 output Boolean success = false;
4180 output FCore.Cache cache;
4181 output Values.Value outValue;
4182 protected
4183 Flags.Flag flags;
4184 algorithm
4185 1 flags := loadCommandLineOptionsFromModel(className);
4186
4187 try
4188 1 (success, cache, outValue) := callTranslateModelFMU(inCache,inEnv,className,FMUVersion,inFMUType,inFileNamePrefix,addDummy,platforms,inSimSettings);
4189 // reset to the original flags
4190 1 FlagsUtil.saveFlags(flags);
4191 else
4192 ✗ FlagsUtil.saveFlags(flags);
4193 ✗ fail();
4194 end try;
4195 end translateModelFMU;
4196
4197 protected function callTranslateModelFMU
4198 "Translates a model into target code and writes CMakeLists.txt"
4199 input FCore.Cache inCache;
4200 input FCore.Graph inEnv;
4201 input Absyn.Path className "path for the model";
4202 input String FMUVersion;
4203 input String inFMUType;
4204 input String inFileNamePrefix;
4205 input Boolean addDummy "if true, add a dummy state";
4206 input list<String> platforms = {"static"};
4207 input Option<SimCode.SimulationSettings> inSimSettings = NONE();
4208 output Boolean success;
4209 output FCore.Cache cache;
4210 output Values.Value outValue;
4211 protected
4212 String filenameprefix, fmuTargetName;
4213 InteractiveTypes.SimulationOptions defaultSimOpt;
4214 SimCode.SimulationSettings simSettings;
4215 list<String> libs;
4216 String FMUType = inFMUType;
4217 Boolean isWasmFMU = isWasmFMUExport(FMUVersion, platforms);
4218 algorithm
4219 1 cache := inCache;
4220
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if not FMI.checkFMIVersion(FMUVersion) then
4221 success :=false;
4222 outValue := Values.STRING("");
4223 ✗ Error.addMessage(Error.UNKNOWN_FMU_VERSION, {FMUVersion});
4224 ✗ return;
4225 elseif not FMI.checkFMIType(FMUType) then
4226 success :=false;
4227 outValue := Values.STRING("");
4228 ✗ Error.addMessage(Error.UNKNOWN_FMU_TYPE, {FMUType});
4229 ✗ return;
4230 end if;
4231
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if not FMI.canExportFMU(FMUVersion, FMUType) then
4232 success :=false;
4233 outValue := Values.STRING("");
4234 ✗ Error.addMessage(Error.FMU_EXPORT_NOT_SUPPORTED, {FMUType, FMUVersion});
4235 ✗ return;
4236 end if;
4237
1/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1 if Config.simCodeTarget() == "Cpp" and FMI.isFMICSType(FMUType) then
4238 ✗ Error.addMessage(Error.FMU_EXPORT_NOT_SUPPORTED_CPP, {FMUType});
4239 FMUType := "me";
4240 end if;
4241
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 if Flags.getConfigBool(Flags.DAE_MODE) and not isWasmFMU then
4242 success := false;
4243 outValue := Values.STRING("");
4244 ✗ if FMI.isFMIMEType(FMUType) then
4245 ✗ Error.addMessage(Error.FMU_EXPORT_DAE_MODE_ME, {FMUType});
4246 else
4247 ✗ Error.addMessage(Error.FMU_EXPORT_DAE_MODE_C_CS, {});
4248 end if;
4249 ✗ return;
4250 end if;
4251
4252 // NOTE: The FMUs use fileNamePrefix for the internal name when it would be expected to be fileNamePrefix that decides the .fmu filename
4253 // The scripting environment from a user's perspective is like that. fmuTargetName is the name of the .fmu in the templates, etc.
4254
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
1 filenameprefix := Util.stringReplaceChar(if inFileNamePrefix == "<default>" then AbsynUtil.pathLastIdent(className) else inFileNamePrefix, ".", "_");
4255
4/8
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 time.
✗ Branch 9 not taken.
1 fmuTargetName := if FMUVersion == "1.0" then filenameprefix else (if inFileNamePrefix == "<default>" then AbsynUtil.pathLastIdent(className) else inFileNamePrefix);
4256
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 if isSome(inSimSettings) then
4257 ✗ SOME(simSettings) := inSimSettings;
4258 else
4259 1 defaultSimOpt := buildSimulationOptionsFromModelExperimentAnnotation(className, filenameprefix, SOME(defaultSimulationOptions));
4260 1 simSettings := convertSimulationOptionsToSimCode(defaultSimOpt);
4261 end if;
4262 // The wasm FMU export uses the wasm-jit code generator, as buildModelFMU does;
4263 // the flag change is reverted by translateModelFMU's saveFlags wrapper.
4264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if isWasmFMU then
4265 ✗ FlagsUtil.setConfigString(Flags.SIMCODE_TARGET, "wasm-jit");
4266 ✗ FlagsUtil.setConfigString(Flags.FMU_NATIVE_PLATFORMS, stringDelimitList(List.select(platforms, isNotWasmPlatform), ","));
4267 end if;
4268 1 FlagsUtil.setConfigBool(Flags.BUILDING_FMU, true);
4269 1 FlagsUtil.setConfigString(Flags.FMI_VERSION, FMUVersion);
4270
4271 try
4272
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
3 (success, cache, libs, _, _) := SimCodeMain.translateModel(SimCodeMain.TranslateModelKind.FMU(FMUType, fmuTargetName, isWasmFMU),
4273 cache, inEnv, className, filenameprefix, true, Flags.getConfigBool(Flags.DAE_MODE), true, SOME(simSettings));
4274 // A wasm translation wrote no FMU: it lowered the model kernel and kept it,
4275 // so force its JIT compile (and resolve its external "C") here, as
4276 // buildModel's compile phase does. The model is then ready to simulate and
4277 // the buildModelFMU that follows only links and renders.
4278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if success and isWasmFMU then
4279 ✗ CodegenWasmJit.finishCompile(filenameprefix);
4280 end if;
4281
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 outValue := Values.STRING((if not Testsuite.isRunning() then System.pwd() + Autoconf.pathDelimiter else "") + fmuTargetName + ".fmu");
4282 else
4283 success :=false;
4284 outValue := Values.STRING("");
4285 end try;
4286 1 FlagsUtil.setConfigBool(Flags.BUILDING_FMU, false);
4287 1 FlagsUtil.setConfigString(Flags.FMI_VERSION, "");
4288 end callTranslateModelFMU;
4289
4290 public function generateFMI3GraphicalRepresentation
4291 "FMI 3.0 graphical user annotations (issue #15686 task 9). From an in-memory
4292 structure holding the model's graphics alone (issue #15219), this renders the
4293 model Icon to terminalsAndIcons/icon.png (+ icon.svg), adds an FMI 3.0
4294 <GraphicalRepresentation> to terminalsAndIcons.xml, and for every placed
4295 connector component renders its port icon to terminalsAndIcons/<iconBaseName>.png
4296 (+ .svg) and adds a <TerminalGraphicalRepresentation> (placement box +
4297 iconBaseName). All icon files live in terminalsAndIcons/ because FMI 3.0
4298 resolves iconBaseName relative to terminalsAndIcons/terminalsAndIcons.xml and
4299 requires a PNG (the SVG is an optional companion). The set of
4300 ports and their input/output direction are NOT taken from the model instance:
4301 structured connectors already have a <Terminal> from SimCode (we only add the
4302 graphics), and a simple signal port gets a terminal whose variableKind is the
4303 flat-model causality read from modelDescription.xml. Best-effort: any failure
4304 (e.g. a model without an icon) is silently ignored so it never blocks the build."
4305 input Absyn.Path className;
4306 input String fmutmp;
4307 input String modelIdentifier;
4308 protected
4309 Integer handle, nConn, i;
4310 String svg, grepr, modelName, taiDir, taiFile, content;
4311 String info, cname, ibase, sx1, sy1, sx2, sy2, csvg, tgr;
4312 list<String> parts;
4313 algorithm
4314 try
4315
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
15 Values.INTEGER(handle) := NFApi.getModelInstanceIconReference(className);
4316
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if handle > 0 then
4317 // Inner try so the model-instance handle is released on EVERY exit path
4318 // (a failure in the graphics work below must not leak the reference).
4319 try
4320 15 modelName := AbsynUtil.pathLastIdent(className);
4321 // FMI 3.0 (section "Distribution of FMUs"): icon image files referenced
4322 // from terminalsAndIcons.xml live in the terminalsAndIcons/ directory, and
4323 // iconBaseName is resolved relative to terminalsAndIcons/terminalsAndIcons.xml.
4324 15 taiDir := fmutmp + "/terminalsAndIcons/";
4325 15 taiFile := taiDir + "terminalsAndIcons.xml";
4326
4327 15 svg := OMGraphics.iconSVGFromHandle(handle, modelName);
4328 15 grepr := OMGraphics.graphicalRepresentationXMLFromHandle(handle, 0.5);
4329 15 nConn := OMGraphics.placedConnectorCount(handle);
4330
4331 // model icon -> terminalsAndIcons/icon.png (mandatory) + icon.svg (optional
4332 // companion). The fixed name "icon" is the FMI 3.0 convention for the FMU
4333 // icon "without terminals".
4334
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
15 if svg <> "" then
4335 4 Util.createDirectoryTree(taiDir);
4336
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if OMGraphics.writeIconPNGFromHandle(handle, modelName, taiDir + "icon.png") then
4337 4 System.writeFile(taiDir + "icon.svg", svg);
4338 else
4339 // icon.png is mandatory for the <Icon> in <GraphicalRepresentation>;
4340 // drop the block rather than reference a file we failed to write.
4341 grepr := "";
4342 end if;
4343 else
4344 grepr := "";
4345 end if;
4346
4347
4/6
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
15 if grepr <> "" or nConn > 0 then
4348 // start from the SimCode-written terminals file, or a fresh skeleton
4349
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 time.
4 if System.regularFileExists(taiFile) then
4350 3 content := System.readFile(taiFile);
4351 else
4352 1 Util.createDirectoryTree(taiDir);
4353 content := "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<fmiTerminalsAndIcons fmiVersion=\"3.0\">\n</fmiTerminalsAndIcons>\n";
4354 end if;
4355
4356 // For each placed connector add its TerminalGraphicalRepresentation and
4357 // render its port icon. The terminal itself (name + member + input/output
4358 // direction) is produced by SimCode from the flat model; here we only add
4359 // the graphics, matched to the existing <Terminal> by the connector name.
4360
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 3 times.
23 for i in 0:nConn-1 loop
4361 19 info := OMGraphics.placedConnectorInfo(handle, i);
4362 19 parts := System.strtok(info, "\t"); // name, iconBaseName, x1, y1, x2, y2
4363
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 if listLength(parts) == 6 then
4364 19 cname := listGet(parts, 1);
4365 19 ibase := listGet(parts, 2);
4366 19 sx1 := listGet(parts, 3);
4367 19 sy1 := listGet(parts, 4);
4368 19 sx2 := listGet(parts, 5);
4369 19 sy2 := listGet(parts, 6);
4370
4371
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
19 if System.stringFind(content, "<Terminal name=\"" + cname + "\"") >= 0 then
4372 // the connector's own port icon -> terminalsAndIcons/<ibase>.png
4373 // (mandatory) + <ibase>.svg (optional). iconBaseName is mandatory on
4374 // TerminalGraphicalRepresentation, so only emit the element when the
4375 // PNG was actually written (a dangling iconBaseName is invalid).
4376 ✗ if OMGraphics.writePlacedConnectorIconPNG(handle, i, taiDir + ibase + ".png") then
4377 ✗ csvg := OMGraphics.placedConnectorIconSVG(handle, i);
4378 ✗ if csvg <> "" then
4379 ✗ System.writeFile(taiDir + ibase + ".svg", csvg);
4380 end if;
4381 ✗ tgr := " <TerminalGraphicalRepresentation x1=\"" + sx1 + "\" y1=\"" + sy1 +
4382 "\" x2=\"" + sx2 + "\" y2=\"" + sy2 + "\" iconBaseName=\"" + ibase + ".png\"/>\n";
4383 ✗ content := insertBeforeTerminalClose(content, cname, tgr);
4384 end if;
4385 end if;
4386 end if;
4387 end for;
4388
4389 // GraphicalRepresentation first (FMI 3.0 schema order: before Terminals)
4390
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
4 if grepr <> "" then
4391 4 content := spliceGraphicalRepresentation(content, grepr);
4392 end if;
4393
4394 4 System.writeFile(taiFile, content);
4395 end if;
4396 else
4397 // release the handle on the failure path, then re-raise so the outer
4398 // try treats it as "no graphics" (best-effort)
4399 ✗ Values.BOOL(_) := NFApi.releaseModelInstanceReference(handle);
4400 fail();
4401 end try;
4402
4403
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
15 Values.BOOL(_) := NFApi.releaseModelInstanceReference(handle);
4404 end if;
4405 else
4406 // no model instance / no graphics: skip graphical representation
4407 end try;
4408 end generateFMI3GraphicalRepresentation;
4409
4410 protected function spliceGraphicalRepresentation
4411 "Insert a <GraphicalRepresentation> block in FMI 3.0 schema order: right before
4412 the <Terminals> open tag when present, otherwise before the closing root tag."
4413 input String content;
4414 input String graphicalRepresentation;
4415 output String result;
4416 algorithm
4417 // FMI 3.0 schema requires GraphicalRepresentation before Terminals. Insert it
4418 // before the <Terminals> open tag, tolerating any indentation (don't depend on
4419 // a two-space prefix); fall back to before the closing root tag when there is
4420 // no Terminals element.
4421
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 time.
4 if System.stringFind(content, " <Terminals>") >= 0 then
4422 3 result := System.stringReplace(content, " <Terminals>", graphicalRepresentation + " <Terminals>");
4423 elseif System.stringFind(content, "<Terminals>") >= 0 then
4424 ✗ result := System.stringReplace(content, "<Terminals>", graphicalRepresentation + "<Terminals>");
4425 else
4426 1 result := System.stringReplace(content, "</fmiTerminalsAndIcons>", graphicalRepresentation + "</fmiTerminalsAndIcons>");
4427 end if;
4428 end spliceGraphicalRepresentation;
4429
4430 protected function insertBeforeTerminalClose
4431 "Insert `insertion` (a TerminalGraphicalRepresentation line) on its own line just
4432 before the </Terminal> that closes the <Terminal name=\"name\" ...> element
4433 emitted by SimCode. The closing tag's own indentation is preserved by inserting
4434 after the newline that precedes it."
4435 input String content;
4436 input String name;
4437 input String insertion;
4438 output String result;
4439 protected
4440 String marker, tail;
4441 Integer p, r, k, len;
4442 algorithm
4443 ✗ marker := "<Terminal name=\"" + name + "\"";
4444 ✗ p := System.stringFind(content, marker);
4445 ✗ len := stringLength(content);
4446 ✗ if p < 0 then
4447 result := content;
4448 else
4449 ✗ tail := substring(content, p + 1, len); // from the opening tag onward
4450 ✗ r := System.stringFind(tail, "</Terminal>");
4451 ✗ if r < 0 then
4452 result := content;
4453 else
4454 // p + r is the 0-based index of '<' of </Terminal>; back up over the close
4455 // tag's leading spaces so the insertion lands after the preceding newline
4456 ✗ k := p + r; // 1-based position of the char before '<'
4457 ✗ while k >= 1 and stringEq(substring(content, k, k), " ") loop
4458 ✗ k := k - 1;
4459 end while;
4460 ✗ result := substring(content, 1, k) + insertion + substring(content, k + 1, len);
4461 end if;
4462 end if;
4463 end insertBeforeTerminalClose;
4464
4465 protected function fmuMethodToSimulationFlag
4466 "`buildModelFMU(method=...)` names the integrator a Co-Simulation FMU embeds,
4467 but an FMU reads its solver from `resources/<prefix>_flags.json`, which only
4468 `--fmiFlags` writes. So fold an explicit method in there, unless the caller
4469 already said `s:`.
4470
4471 Only a method the FMU can integrate with: C's `FMI2CS_initializeSolverData`
4472 takes `euler`/`cvode` and rejects the rest at instantiation (so a model's own
4473 `dassl` default must not become `s:dassl`); a wasm FMU serves the whole
4474 wasm-jit driver set. An unaccepted method is left out, and the FMU falls back
4475 to what it defaults to without one: euler for C, the model's own method (else
4476 DASKR) for wasm."
4477 input String method;
4478 input Boolean isWasmFMU;
4479 protected
4480 list<String> fmiFlags;
4481 list<String> accepted = if isWasmFMU then CodegenWasmJit.fmuCsSolvers() else {"euler", "cvode"};
4482 algorithm
4483
2/6
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
88 if method == "<default>" or not listMember(method, accepted) then
4484 88 return;
4485 end if;
4486 ✗ fmiFlags := Flags.getConfigStringList(Flags.FMI_FLAGS);
4487 ✗ for f in fmiFlags loop
4488 ✗ if StringUtil.startsWith(f, "s:") then
4489 ✗ return;
4490 end if;
4491 end for;
4492 // `none` and a `*.json` path are whole-value settings, not a list to extend.
4493 ✗ if not listEmpty(fmiFlags) and not stringEq(listHead(fmiFlags), "default") then
4494 ✗ return;
4495 end if;
4496 ✗ FlagsUtil.setConfigStringList(Flags.FMI_FLAGS, {"s:" + method});
4497 end fmuMethodToSimulationFlag;
4498
4499 protected function fmuAnnotationSimulationFlags
4500 "A wasm FMU runs the model with the flags simulate() would: the class's
4501 __OpenModelica_simulationFlags go into --fmiFlags, whose `_flags.json` the FMU
4502 applies when it instantiates. A flag already named wins, and one the FMU cannot
4503 honour is left out rather than baked in to fail at the importer's first
4504 instantiate. A C FMU reads only a few flags and warns about the rest, so it
4505 keeps to what --fmiFlags said."
4506 input Absyn.Path className;
4507 input Boolean isWasmFMU;
4508 protected
4509 list<String> fmiFlags, names = {}, folded = {};
4510 list<Absyn.ElementArg> args;
4511 Option<Absyn.Modification> mod;
4512 String name, value;
4513 algorithm
4514
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
88 if not isWasmFMU or Flags.getConfigBool(Flags.IGNORE_SIMULATION_FLAGS_ANNOTATION) then
4515 88 return;
4516 end if;
4517 ✗ fmiFlags := Flags.getConfigStringList(Flags.FMI_FLAGS);
4518 ✗ if listLength(fmiFlags) == 1 and stringEq(listHead(fmiFlags), "default") then
4519 fmiFlags := {};
4520 end if;
4521 // `none` and a `*.json` path are whole-value settings, not a list to extend.
4522 ✗ for f in fmiFlags loop
4523 ✗ if not stringEq(f, "default") and not (listLength(Util.stringSplitAtChar(f, ":")) == 2) then
4524 ✗ return;
4525 end if;
4526 ✗ names := listHead(Util.stringSplitAtChar(f, ":")) :: names;
4527 end for;
4528 ✗ loadProgram(className);
4529 ✗ mod := ProgramUtil.getNamedAnnotationExp(className, SymbolTable.getAbsyn(),
4530 Absyn.IDENT("__OpenModelica_simulationFlags"), SOME(NONE()), Util.id);
4531 args := match mod
4532 case SOME(Absyn.CLASSMOD(elementArgLst = args)) then args;
4533 else {};
4534 end match;
4535 ✗ for arg in args loop
4536 ✗ name := AbsynUtil.pathString(AbsynUtil.elementArgName(arg));
4537 ✗ value := fmuSimulationFlagValue(arg);
4538 ✗ if not listMember(name, names) then
4539 ✗ if CodegenWasmJit.fmuAcceptsFlag(name, value) then
4540 ✗ folded := (name + ":" + value) :: folded;
4541 else
4542 ✗ Error.addCompilerNotification("Leaving the __OpenModelica_simulationFlags entry " + name
4543 + "=\"" + value + "\" out of the FMU: it cannot honour it.");
4544 end if;
4545 end if;
4546 end for;
4547 ✗ if not listEmpty(folded) then
4548 ✗ FlagsUtil.setConfigStringList(Flags.FMI_FLAGS, listAppend(fmiFlags, listReverse(folded)));
4549 end if;
4550 end fmuAnnotationSimulationFlags;
4551
4552 protected function fmuSimulationFlagValue
4553 "One __OpenModelica_simulationFlags entry as a `_flags.json` value; empty for a
4554 flag that takes none."
4555 input Absyn.ElementArg arg;
4556 output String value;
4557 algorithm
4558 value := match arg
4559 local
4560 Absyn.Exp exp;
4561 case Absyn.ElementArg.MODIFICATION(modification =
4562 SOME(Absyn.Modification.CLASSMOD(eqMod = Absyn.EqMod.EQMOD(exp = exp))))
4563 then
4564 match exp
4565 case Absyn.STRING("()") then "";
4566 ✗ case Absyn.STRING() then exp.value;
4567 ✗ else Dump.printExpStr(exp);
4568 end match;
4569 else "";
4570 end match;
4571 end fmuSimulationFlagValue;
4572
4573 protected function reportFMUPlatformsBuilt
4574 "The platform progress the C export reports around each platform's compile.
4575 A wasm FMU is already linked by the time `translateModel` returns, so the pair
4576 is reported once the .fmu is there — which is where the C export's own
4577 messages land relative to the translation's, so the log reads the same either
4578 way."
4579 input list<String> platforms;
4580 protected
4581 Integer platformIndex = 0, platformCount = listLength(platforms);
4582 String platformName;
4583 algorithm
4584 ✗ for platform in platforms loop
4585 ✗ platformIndex := platformIndex + 1;
4586 ✗ platformName := listGet(Util.stringSplitAtChar(platform, " "), 1);
4587 ✗ System.reportProgress(intDiv((platformIndex - 1) * 1000, platformCount), 4 /* PHASE_BACKEND */);
4588 ✗ System.reportProgressMessage("Building FMU for " + platformName + " (" + String(platformIndex) + "/" + String(platformCount) + ")");
4589 ✗ Error.addCompilerNotification("Building FMU for platform '" + platformName + "' (" + String(platformIndex) + "/" + String(platformCount) + ").");
4590 ✗ Error.addCompilerNotification("Finished FMU for platform '" + platformName + "' (" + String(platformIndex) + "/" + String(platformCount) + ").");
4591 end for;
4592 ✗ System.reportProgress(1000, 4 /* PHASE_BACKEND */);
4593 end reportFMUPlatformsBuilt;
4594
4595 protected function fmuSimulationSettings
4596 "The SimulationSettings an FMU export runs with: the model's experiment defaults,
4597 with `method` folded in when it is not \"<default>\" (a Co-Simulation FMU embeds
4598 its integrator, so the solver is chosen at export time)."
4599 input Absyn.Path className;
4600 input String inFileNamePrefix;
4601 input String method = "<default>";
4602 output SimCode.SimulationSettings simSettings;
4603 protected
4604 String filenameprefix;
4605 algorithm
4606
3/4
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 19 times.
✓ Branch 3 taken 71 times.
✗ Branch 4 not taken.
90 filenameprefix := Util.stringReplaceChar(if inFileNamePrefix == "<default>" then AbsynUtil.pathLastIdent(className) else inFileNamePrefix, ".", "_");
4607 90 simSettings := convertSimulationOptionsToSimCode(
4608 buildSimulationOptionsFromModelExperimentAnnotation(className, filenameprefix, SOME(defaultSimulationOptions)));
4609
2/4
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 90 times.
✗ Branch 4 not taken.
90 if method <> "<default>" then
4610 ✗ simSettings.method := method;
4611 end if;
4612 end fmuSimulationSettings;
4613
4614 protected function buildModelFMU
4615 input FCore.Cache inCache;
4616 input FCore.Graph inEnv;
4617 input Absyn.Path className "path for the model";
4618 input String FMUVersion;
4619 input String inFMUType;
4620 input String inFileNamePrefix;
4621 input Boolean addDummy "if true, add a dummy state";
4622 input list<String> platforms = {"static"};
4623 input Option<SimCode.SimulationSettings> inSimSettings = NONE();
4624 input String method = "<default>" "`buildModelFMU(method=)`, folded into --fmiFlags where the FMU accepts it";
4625 output FCore.Cache cache;
4626 output Values.Value outValue;
4627 protected
4628 Flags.Flag flags;
4629 list<String> fmiFlags;
4630 algorithm
4631
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
88 if isProtectedContentAccess(className) then
4632 // if AST contains encrypted class show nothing
4633 cache := inCache;
4634 ✗ outValue := Values.STRING("");
4635 else
4636 88 flags := loadCommandLineOptionsFromModel(className);
4637 // `method=` reaches the FMU only through --fmiFlags, a global: restore it by
4638 // hand so one export does not pick the solver for the next. `saveFlags` will
4639 // not — without __OpenModelica_commandLineOptions `flags` aliases the store.
4640 88 fmiFlags := Flags.getConfigStringList(Flags.FMI_FLAGS);
4641 88 fmuMethodToSimulationFlag(method, isWasmFMUExport(FMUVersion, platforms));
4642 88 fmuAnnotationSimulationFlags(className, isWasmFMUExport(FMUVersion, platforms));
4643
4644 try
4645 88 (cache, outValue) := callBuildModelFMU(inCache,inEnv,className,FMUVersion,inFMUType,inFileNamePrefix,addDummy,platforms,inSimSettings);
4646 // reset to the original flags
4647 88 FlagsUtil.setConfigStringList(Flags.FMI_FLAGS, fmiFlags);
4648 88 FlagsUtil.saveFlags(flags);
4649 else
4650 ✗ FlagsUtil.setConfigStringList(Flags.FMI_FLAGS, fmiFlags);
4651 ✗ FlagsUtil.saveFlags(flags);
4652 ✗ fail();
4653 end try;
4654 end if;
4655 end buildModelFMU;
4656
4657 public function callBuildModelFMU
4658 " Author: Frenkel TUD
4659 Translates a model into target code and writes also a makefile."
4660 input FCore.Cache inCache;
4661 input FCore.Graph inEnv;
4662 input Absyn.Path className "path for the model";
4663 input String FMUVersion;
4664 input String inFMUType;
4665 input String inFileNamePrefix;
4666 input Boolean addDummy "if true, add a dummy state";
4667 input list<String> platforms = {"static"};
4668 input Option<SimCode.SimulationSettings> inSimSettings = NONE();
4669 output FCore.Cache cache;
4670 output Values.Value outValue;
4671 protected
4672 Boolean success;
4673 String filenameprefix, fmutmp, logfile, configureLogFile, dir, cmd, msvcEnv;
4674 String fmuTargetName;
4675 SimCode.SimulationSettings simSettings;
4676 list<String> libs = {} "the reuse path translates nothing, so nothing reports libraries";
4677 Boolean isWindows;
4678 Boolean needs3rdPartyLibs;
4679 Integer platformIndex, platformCount;
4680 String platformName;
4681 String FMUType = inFMUType;
4682 // FMI 1.0 is deprecated and the wasm export does not serve it; such a request
4683 // is the C export's business even under the wasm simCodeTarget.
4684 Boolean wasmRequested = listMember("wasm", platforms);
4685 Boolean wasmTarget = Config.simCodeTarget() == "wasm-jit" or Config.simCodeTarget() == "wasm";
4686 Boolean isWasmFMU = isWasmFMUExport(FMUVersion, platforms);
4687 Option<SimCode.SimCode> keptSimCode;
4688 SimCode.SimCode keptTranslation;
4689 // Reached through the target, the caller still wants an FMU the ordinary
4690 // tooling can load, so it gets this machine's platform too.
4691 list<String> nativePlatforms = if wasmRequested then List.select(platforms, isNotWasmPlatform) else {"native"};
4692 algorithm
4693 90 cache := inCache;
4694
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
90 if not FMI.checkFMIVersion(FMUVersion) then
4695 outValue := Values.STRING("");
4696 ✗ Error.addMessage(Error.UNKNOWN_FMU_VERSION, {FMUVersion});
4697 ✗ return;
4698 elseif not FMI.checkFMIType(FMUType) then
4699 outValue := Values.STRING("");
4700 ✗ Error.addMessage(Error.UNKNOWN_FMU_TYPE, {FMUType});
4701 ✗ return;
4702 end if;
4703
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
90 if not FMI.canExportFMU(FMUVersion, FMUType) then
4704 outValue := Values.STRING("");
4705 ✗ Error.addMessage(Error.FMU_EXPORT_NOT_SUPPORTED, {FMUType, FMUVersion});
4706 ✗ return;
4707 end if;
4708
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
90 if wasmRequested and FMUVersion == "1.0" then
4709 outValue := Values.STRING("");
4710 ✗ Error.addMessage(Error.FMU_EXPORT_WASM_FMI1, {});
4711 ✗ return;
4712 end if;
4713
4/6
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 81 times.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 9 times.
90 if Config.simCodeTarget() == "Cpp" and FMI.isFMICSType(FMUType) then
4714 ✗ Error.addMessage(Error.FMU_EXPORT_NOT_SUPPORTED_CPP, {FMUType});
4715 FMUType := "me";
4716 end if;
4717
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
90 if Flags.getConfigBool(Flags.DAE_MODE) and not isWasmFMU then
4718 outValue := Values.STRING("");
4719 ✗ if FMI.isFMIMEType(FMUType) then
4720 ✗ Error.addMessage(Error.FMU_EXPORT_DAE_MODE_ME, {FMUType});
4721 else
4722 ✗ Error.addMessage(Error.FMU_EXPORT_DAE_MODE_C_CS, {});
4723 end if;
4724 ✗ return;
4725 end if;
4726
4727 // NOTE: The FMUs use fileNamePrefix for the internal name when it would be expected to be fileNamePrefix that decides the .fmu filename
4728 // The scripting environment from a user's perspective is like that. fmuTargetName is the name of the .fmu in the templates, etc.
4729
3/4
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 19 times.
✓ Branch 3 taken 71 times.
✗ Branch 4 not taken.
90 filenameprefix := Util.stringReplaceChar(if inFileNamePrefix == "<default>" then AbsynUtil.pathLastIdent(className) else inFileNamePrefix, ".", "_");
4730
6/8
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 87 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 68 times.
✓ Branch 6 taken 19 times.
✓ Branch 8 taken 68 times.
✗ Branch 9 not taken.
90 fmuTargetName := if FMUVersion == "1.0" then filenameprefix else (if inFileNamePrefix == "<default>" then AbsynUtil.pathLastIdent(className) else inFileNamePrefix);
4731
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 88 times.
90 if isSome(inSimSettings) then
4732 88 SOME(simSettings) := inSimSettings;
4733 else
4734 2 simSettings := fmuSimulationSettings(className, inFileNamePrefix);
4735 end if;
4736 // The wasm FMU export uses the wasm-jit code generator; the flag change is
4737 // reverted by buildModelFMU's saveFlags wrapper.
4738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 if isWasmFMU then
4739 ✗ FlagsUtil.setConfigString(Flags.SIMCODE_TARGET, "wasm-jit");
4740 // Every other entry names a native platform the FMU should also serve.
4741 ✗ FlagsUtil.setConfigString(Flags.FMU_NATIVE_PLATFORMS, stringDelimitList(nativePlatforms, ","));
4742 elseif wasmTarget then
4743 // A browser omc has no C code generator and says so from there.
4744 ✗ FlagsUtil.setConfigString(Flags.SIMCODE_TARGET, "C");
4745 end if;
4746 90 FlagsUtil.setConfigBool(Flags.BUILDING_FMU, true);
4747 90 FlagsUtil.setConfigString(Flags.FMI_VERSION, FMUVersion);
4748 // A translateModelFMU of this model, this FMI version and this kind of
4749 // interface, off the program still loaded and under the flags still set, has
4750 // already done the translation: render the metadata and link the adapter onto
4751 // the kernel it left rather than translating again. The flags are read after
4752 // the munging above so both phases fingerprint the same state.
4753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 keptSimCode := if isWasmFMU then SimCodeMain.fmuTranslationFor(FMUVersion, FMUType, className, SOME(simSettings)) else NONE();
4754 try
4755
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 90 times.
90 if isSome(keptSimCode) then
4756 ✗ SOME(keptTranslation) := keptSimCode;
4757 ✗ Error.addCompilerNotification("Exporting the translation translateModelFMU already made; the model is not translated again.");
4758 ✗ SimCodeMain.emitWasmFMU(keptTranslation, FMUVersion, FMUType, SymbolTable.getAbsyn());
4759 success := true;
4760 else
4761 180 (success, cache, libs, _, _) := SimCodeMain.translateModel(SimCodeMain.TranslateModelKind.FMU(FMUType, fmuTargetName, false),
4762 cache, inEnv, className, filenameprefix, true, Flags.getConfigBool(Flags.DAE_MODE), true, SOME(simSettings));
4763 end if;
4764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 true := success;
4765
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 88 times.
90 outValue := Values.STRING((if not Testsuite.isRunning() then System.pwd() + Autoconf.pathDelimiter else "") + fmuTargetName + ".fmu");
4766 else
4767 outValue := Values.STRING("");
4768 ✗ FlagsUtil.setConfigBool(Flags.BUILDING_FMU, false);
4769 ✗ FlagsUtil.setConfigString(Flags.FMI_VERSION, "");
4770 ✗ return;
4771 end try;
4772 90 FlagsUtil.setConfigBool(Flags.BUILDING_FMU, false);
4773 90 FlagsUtil.setConfigString(Flags.FMI_VERSION, "");
4774
4775 90 System.realtimeTick(ClockIndexes.RT_CLOCK_BUILD_MODEL);
4776
4777 isWindows := Autoconf.os == "Windows_NT";
4778
4779 90 fmutmp := Util.hashFileNamePrefix(filenameprefix) + ".fmutmp";
4780 90 logfile := filenameprefix + ".log";
4781 90 dir := fmutmp+"/sources/";
4782
4783 // wasm FMU: CodegenWasmJit.emitMeFmu already wrote the self-contained
4784 // <name>.fmu (component linked in Rust, ZIP assembled in Rust) — nothing to
4785 // build or zip. Just confirm it exists. With --fmuDirectory it is an unzipped
4786 // directory of that name instead.
4787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 if isWasmFMU then
4788 ✗ if not (System.regularFileExists(fmuTargetName + ".fmu")
4789 or (Flags.getConfigBool(Flags.FMU_DIRECTORY) and System.directoryExists(fmuTargetName + ".fmu"))) then
4790 ✗ Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {"wasm FMU export produced no " + fmuTargetName + ".fmu"});
4791 outValue := Values.STRING("");
4792 ✗ return;
4793 end if;
4794 ✗ reportFMUPlatformsBuilt(platforms);
4795 ✗ return;
4796 end if;
4797
4798
3/4
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 81 times.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
90 if Config.simCodeTarget() == "Cpp" then
4799 9 System.removeDirectory("binaries");
4800
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for platform in platforms loop
4801
3/8
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 9 times.
✗ Branch 9 not taken.
9 if platform == "dynamic" or platform == "static" then
4802 9 CevalScript.compileModel(filenameprefix + "_FMU", libs);
4803 else
4804 ✗ CevalScript.compileModel(filenameprefix + "_FMU", libs,
4805 makeVars={"TARGET_TRIPLET=" + platform});
4806 end if;
4807 9 ExecStat.execStat("buildModelFMU: Generate C++ for platform " + platform);
4808 end for;
4809 9 if 0 <> System.systemCallRestrictedEnv(Autoconf.make + " -f " + filenameprefix + "_FMU.makefile clean", outFile=logfile) then
4810 // do nothing
4811 end if;
4812 9 return;
4813 end if;
4814 81 CevalScript.compileModel(filenameprefix+"_FMU" , libs);
4815 81 ExecStat.execStat("buildModelFMU: Generate the FMI files");
4816
4817 // Check flag fmiFlags if we need additional 3rdParty runtime libs and files
4818 81 needs3rdPartyLibs := SimCodeUtil.cvodeFmiFlagIsSet(SimCodeUtil.createFMISimulationFlags(false));
4819
4820 // A docker build compiles the FMU from sources/, which --fmiSources=false only
4821 // strips when packing, so the Rust half has to be there too.
4822
4/6
✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 74 times.
✓ Branch 6 taken 7 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 74 times.
81 if Config.simCodeRustRuntime() and not System.directoryExists(fmutmp + "/sources/rust")
4823 and List.any(platforms, isDockerPlatform) then
4824 ✗ SimCodeMain.copyFmuRustSources(fmutmp);
4825 end if;
4826
4827 // Configure and build the FMU with CMake
4828 // Compiling for several platforms takes minutes per platform, so report which one is
4829 // being built. Error.checkCancel() hands the thread to the host UI between platforms,
4830 // which is what keeps OMEdit responsive and lets Cancel through.
4831 81 platformCount := listLength(platforms);
4832 platformIndex := 0;
4833
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 81 times.
162 for platform in platforms loop
4834 81 platformIndex := platformIndex + 1;
4835 81 platformName := listGet(Util.stringSplitAtChar(platform, " "), 1);
4836 81 Error.checkCancel();
4837
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 System.reportProgress(intDiv((platformIndex - 1) * 1000, platformCount), 4 /* PHASE_BACKEND */);
4838 81 System.reportProgressMessage("Building FMU for " + platformName + " (" + String(platformIndex) + "/" + String(platformCount) + ")");
4839 81 Error.addCompilerNotification("Building FMU for platform '" + platformName + "' (" + String(platformIndex) + "/" + String(platformCount) + ").");
4840
4841 81 configureLogFile := System.realpath(fmutmp)+"/resources/"+System.stringReplace(platformName,"/","-")+".log";
4842 81 configureFMU_cmake(platform, fmutmp, filenameprefix, configureLogFile, libs, isWindows, needs3rdPartyLibs);
4843
4/4
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 1 time.
✓ Branch 4 taken 79 times.
✓ Branch 5 taken 1 time.
81 if Flags.getConfigEnum(Flags.FMI_FILTER) == Flags.FMI_BLACKBOX or Flags.getConfigEnum(Flags.FMI_FILTER) == Flags.FMI_PROTECTED then
4844 80 System.removeFile(configureLogFile);
4845 end if;
4846 81 Error.addCompilerNotification("Finished FMU for platform '" + platformName + "' (" + String(platformIndex) + "/" + String(platformCount) + ").");
4847 81 ExecStat.execStat("buildModelFMU: Generate platform " + platform);
4848 end for;
4849 81 System.reportProgress(1000, 4 /* PHASE_BACKEND */);
4850 81 System.reportProgressMessage("Packing FMU");
4851 81 Error.checkCancel();
4852
4853 // check for '--fmiSources=false' or '--fmiFilter=blackBox' and remove the sources directory before packing the fmu
4854
3/4
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 74 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
81 if Flags.getConfigEnum(Flags.FMI_SOURCES) == Flags.FMI_SOURCES_NONE or Flags.getConfigEnum(Flags.FMI_FILTER) == Flags.FMI_BLACKBOX then
4855
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 74 times.
74 if not System.removeDirectory(fmutmp + "/sources/") then
4856 ✗ Error.addInternalError("Failed to remove directory: " + fmutmp, sourceInfo());
4857 end if;
4858 end if;
4859
4860 81 msvcEnv := SimCodeUtil.msvcEnvironment();
4861
2/4
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 81 times.
81 if msvcEnv <> "" then
4862 ✗ cmd := msvcEnv + Autoconf.cmake + " -E rm -f \"" + fmuTargetName + ".fmu\" && cd \"" + fmutmp + "\" && " +
4863 Autoconf.cmake + " -E tar cf \"../" + fmuTargetName + ".fmu\" --format=zip .";
4864 else
4865 81 cmd := "rm -f \"" + fmuTargetName + ".fmu\" && cd \"" + fmutmp + "\" && zip -r \"../" + fmuTargetName + ".fmu\" *";
4866 end if;
4867
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 81 times.
81 if 0 <> System.systemCall(cmd, outFile=logfile) then
4868 ✗ Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {cmd + "\n\n" + System.readFile(logfile)});
4869 ✗ ExecStat.execStat("buildModelFMU failed");
4870 end if;
4871
4872
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
81 if not System.regularFileExists(fmuTargetName + ".fmu") then
4873 ✗ Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {"Build commands returned success, but " + fmuTargetName + ".fmu does not exist"});
4874 ✗ fail();
4875 end if;
4876
4877
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 81 times.
81 if not Flags.isSet(Flags.GEN_DEBUG_SYMBOLS) then
4878
1/2
✓ Branch 1 taken 81 times.
✗ Branch 2 not taken.
81 if not System.removeDirectory(fmutmp) then
4879 ✗ Error.addInternalError("Failed to remove directory: " + fmutmp, sourceInfo());
4880 end if;
4881 end if;
4882 end callBuildModelFMU;
4883
4884 protected function isWasmFMUExport
4885 "Whether `buildModelFMU` takes the wasm (fmi-ls-wasm) route: the `wasm` platform
4886 was asked for, or the simCodeTarget is already a wasm one. FMI 1.0 never does."
4887 input String FMUVersion;
4888 input list<String> platforms;
4889 output Boolean isWasm;
4890 algorithm
4891
3/14
✓ Branch 1 taken 267 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 267 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 267 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
267 isWasm := (listMember("wasm", platforms) or Config.simCodeTarget() == "wasm-jit"
4892 or Config.simCodeTarget() == "wasm") and FMUVersion <> "1.0";
4893 end isWasmFMUExport;
4894
4895 protected function isNotWasmPlatform
4896 "\"static\"/\"dynamic\" are the C target's own platform names, meaningless once
4897 the export is a wasm one; every other entry names a native platform."
4898 input String platform;
4899 output Boolean keep = not (platform == "wasm" or platform == "static" or platform == "dynamic");
4900 end isNotWasmPlatform;
4901
4902 protected function buildEncryptedPackage
4903 input Absyn.Path className "path for the model";
4904 input Boolean encrypt;
4905 input Absyn.Program inProgram;
4906 output Boolean success = false;
4907 protected
4908 Absyn.Class cls;
4909 String fileName, logFile, omhome, pd, ext, packageTool, packageToolArgs, command;
4910 Boolean runCommand;
4911 String molName, dirPath, rmCommand, cdCommand, mvCommand, dirOrFileName, zipCommand;
4912 algorithm
4913 1 cls := ProgramUtil.getPathedClassInProgram(className, inProgram);
4914 1 fileName := AbsynUtil.classFilename(cls);
4915 logFile := "buildEncryptedPackage.log";
4916 runCommand := true;
4917
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 if (System.regularFileExists(fileName)) then
4918 // get OPENMODELICAHOME
4919 1 omhome := Settings.getInstallationDirectoryPath();
4920 pd := Autoconf.pathDelimiter;
4921 ext := if Autoconf.os == "Windows_NT" then ".exe" else "";
4922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if encrypt then
4923 // create the path till packagetool
4924 ✗ packageTool := stringAppendList({omhome,pd,"bin",pd,"omc-semla",pd,"packagetool",ext});
4925 ✗ if System.regularFileExists(packageTool) then
4926 // create the list of arguments for packagetool
4927 ✗ packageToolArgs := "-librarypath \"" + System.dirname(fileName) + "\" -version \"1.0\" -language \"3.2\" -encrypt \"" + boolString(encrypt) + "\"";
4928 ✗ command := stringAppendList({"\"",packageTool,"\""," ",packageToolArgs});
4929 else
4930 ✗ Error.addMessage(Error.ENCRYPTION_NOT_SUPPORTED, {packageTool});
4931 runCommand := false;
4932 command := "";
4933 end if;
4934 else
4935 1 molName := AbsynUtil.pathString(className) + ".mol";
4936 1 dirPath := System.dirname(fileName);
4937 // commands
4938 1 rmCommand := "rm -f \"" + molName + "\"";
4939 1 cdCommand := "cd \"" + dirPath + "\"";
4940 1 mvCommand := "mv \"" + molName +"\" \"" + System.pwd() + "\"";
4941
4942
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 if (StringUtil.endsWith(fileName, "package.mo")) then
4943 1 dirOrFileName := System.basename(dirPath);
4944 1 zipCommand := "zip -r \"" + System.pwd() + pd + molName + "\" \"" + dirOrFileName + "\"";
4945 1 command := stringAppendList({rmCommand, " && ", cdCommand, " && cd .. && ", zipCommand});
4946 else
4947 ✗ dirOrFileName := System.basename(fileName);
4948 ✗ zipCommand := "zip -r \"" + System.pwd() + pd + molName + "\" \"" + dirOrFileName + "\"";
4949 ✗ command := stringAppendList({rmCommand, " && ", cdCommand, " && ", zipCommand});
4950 end if;
4951 end if;
4952
4953 if runCommand then
4954 // remove the logFile if it already exists.
4955
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if System.regularFileExists(logFile) then
4956 ✗ System.removeFile(logFile);
4957 end if;
4958 // run the command
4959 1 success := 0 == System.systemCall(command, logFile);
4960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if not(success) then
4961 ✗ Error.addCompilerError("Command failed: " + command);
4962 end if;
4963 end if;
4964 else
4965 ✗ Error.addMessage(Error.FILE_NOT_FOUND_ERROR, {fileName});
4966 end if;
4967 end buildEncryptedPackage;
4968
4969 protected function translateModelXML " author: Alachew
4970 translates a model into XML code "
4971 input output FCore.Cache cache;
4972 input FCore.Graph env;
4973 input Absyn.Path className "path for the model";
4974 output Values.Value outValue;
4975 input String fileNamePrefix;
4976 input Boolean addDummy "if true, add a dummy state";
4977 input Option<SimCode.SimulationSettings> inSimSettingsOpt;
4978 protected
4979 Boolean success;
4980 algorithm
4981 ✗ if isProtectedContentAccess(className) then
4982 // if AST contains encrypted class show nothing
4983 outValue := Values.STRING("");
4984 else
4985 ✗ (success,cache) := SimCodeMain.translateModel(SimCodeMain.TranslateModelKind.XML(), cache, env, className, fileNamePrefix, true, false, true, inSimSettingsOpt);
4986 ✗ outValue := Values.STRING(if success then ((if not Testsuite.isRunning() then System.pwd() + Autoconf.pathDelimiter else "") + fileNamePrefix+".xml") else "");
4987 end if;
4988 end translateModelXML;
4989
4990 public function translateGraphics "function: translates the graphical annotations from old to new version"
4991 input Absyn.Path className;
4992 input Absyn.Msg inMsg;
4993 output Values.Value outValue;
4994 algorithm
4995 outValue := matchcontinue inMsg
4996 local
4997 Absyn.Program p;
4998 String errorMsg,retStr,s1;
4999 Absyn.Class cls, refactoredClass;
5000 Absyn.Within within_;
5001 Boolean strEmpty;
5002
5003 case _
5004 algorithm
5005 ✗ p := SymbolTable.getAbsyn();
5006 ✗ cls := ProgramUtil.getPathedClassInProgram(className, p);
5007 ✗ refactoredClass := Refactor.refactorGraphicalAnnotation(p, cls);
5008 ✗ within_ := ProgramUtil.buildWithin(className);
5009 ✗ SymbolTable.setAbsyn(ProgramUtil.updateProgram(Absyn.PROGRAM({refactoredClass}, within_), p));
5010 ✗ s1 := AbsynUtil.pathString(className);
5011 ✗ retStr:=stringAppendList({"Translation of ",s1," successful.\n"});
5012 ✗ then Values.STRING(retStr);
5013
5014 else
5015 algorithm
5016 ✗ errorMsg := Error.printMessagesStr(false);
5017 ✗ strEmpty := (stringCompare("",errorMsg)==0);
5018 ✗ errorMsg := if strEmpty then "Internal error, translating graphics to new version" else errorMsg;
5019 ✗ then Values.STRING(errorMsg);
5020 end matchcontinue;
5021 end translateGraphics;
5022
5023
5024 protected function calculateSimulationSettings " author: x02lucpo
5025 calculates the start,end,interval,stepsize, method and initFileName"
5026 input FCore.Cache inCache;
5027 input list<Values.Value> vals;
5028 output FCore.Cache outCache;
5029 output SimCode.SimulationSettings outSimSettings;
5030 algorithm
5031 (outCache,outSimSettings) := match (inCache,vals)
5032 local
5033 String method_str,options_str,outputFormat_str,variableFilter_str;
5034 Values.Value starttime_v,stoptime_v,tolerance_v;
5035 Integer interval_i;
5036 Real starttime_r,stoptime_r,tolerance_r;
5037 FCore.Cache cache;
5038 String cflags, simflags;
5039 case (cache, {Values.CODE(Absyn.C_TYPENAME(_)),starttime_v,stoptime_v,Values.INTEGER(interval_i),tolerance_v,Values.STRING(method_str),_,Values.STRING(options_str),Values.STRING(outputFormat_str),Values.STRING(variableFilter_str),Values.STRING(cflags),Values.STRING(simflags)})
5040 algorithm
5041 2366 starttime_r := ValuesUtil.valueReal(starttime_v);
5042 2366 stoptime_r := ValuesUtil.valueReal(stoptime_v);
5043 2366 tolerance_r := ValuesUtil.valueReal(tolerance_v);
5044 2366 outSimSettings := SimCodeMain.createSimulationSettings(starttime_r,stoptime_r,interval_i,tolerance_r,method_str,options_str,outputFormat_str,variableFilter_str,cflags,simflags);
5045 then
5046 (cache, outSimSettings);
5047 else
5048 algorithm
5049 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"CevalScript.calculateSimulationSettings failed: " + ValuesDump.valString(Values.TUPLE(vals))});
5050 ✗ then
5051 fail();
5052 end match;
5053 end calculateSimulationSettings;
5054
5055 protected function getListFirstShowError
5056 "@author: adrpo
5057 return the first element in the list and the rest of values.
5058 if the list is empty display the errorMessage!"
5059 input list<Values.Value> inValues;
5060 input String errorMessage;
5061 output Values.Value outValue;
5062 output list<Values.Value> restValues;
5063 algorithm
5064 (outValue, restValues) := match inValues
5065 local
5066 Values.Value v;
5067 list<Values.Value> rest;
5068
5069 // everything is fine and dandy
5070 case v::rest then (v, rest);
5071
5072 // ups, we're missing an argument
5073 case {}
5074 algorithm
5075 ✗ Error.addMessage(Error.INTERNAL_ERROR, {errorMessage});
5076 ✗ then
5077 fail();
5078 end match;
5079 end getListFirstShowError;
5080
5081 protected function getListNthShowError
5082 "@author: adrpo
5083 return the N-th element in the list and the rest of values.
5084 if the list is empty display the errorMessage!"
5085 input list<Values.Value> inValues;
5086 input String errorMessage;
5087 input Integer currentElement;
5088 input Integer nthElement;
5089 output Values.Value outValue;
5090 algorithm
5091 outValue := matchcontinue(inValues, currentElement, nthElement)
5092 local
5093 Values.Value v;
5094 list<Values.Value> lst,rest;
5095 Integer i,n;
5096
5097 // everything is fine and dandy
5098 case (lst, i, n)
5099 algorithm
5100
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 26 times.
39 true := i < n;
5101 26 (_,rest) := getListFirstShowError(lst,errorMessage);
5102 26 v := getListNthShowError(rest,errorMessage, i+1, n);
5103 then v;
5104
5105 // everything is fine and dandy
5106 case (lst, _, _)
5107 algorithm
5108 13 (v, _) := getListFirstShowError(lst,errorMessage);
5109 then v;
5110
5111 end matchcontinue;
5112 end getListNthShowError;
5113
5114 protected function moveClass
5115 "Moves the referenced class by a certain offset in the given program, relative
5116 to other classes."
5117 input Absyn.Path inClassName;
5118 input Integer inOffset;
5119 input Absyn.Program inProgram;
5120 output Absyn.Program outProgram;
5121 output Boolean outSuccess;
5122 protected
5123 Absyn.Path parent_cls;
5124 String cls_name;
5125 algorithm
5126 // No offset, nothing to do.
5127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if inOffset == 0 then
5128 outProgram := inProgram;
5129 outSuccess := true;
5130 ✗ return;
5131 end if;
5132
5133 try
5134
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if AbsynUtil.pathIsIdent(inClassName) then
5135 // Simple identifier, move a top-level class in the program.
5136 ✗ outProgram := moveClassInProgram(AbsynUtil.pathFirstIdent(inClassName), inOffset, inProgram);
5137 else
5138 // Qualified identifier, move the class inside its parent.
5139
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 (parent_cls, Absyn.IDENT(cls_name)) := AbsynUtil.splitQualAndIdentPath(inClassName);
5140 1 outProgram := Interactive.transformPathedClassInProgram(parent_cls, inProgram,
5141 function moveClassInClass(inName = cls_name, inOffset = inOffset));
5142 end if;
5143
5144 outSuccess := true;
5145 else
5146 outProgram := inProgram;
5147 outSuccess := false;
5148 end try;
5149 end moveClass;
5150
5151 protected function moveClassToTop
5152 "Moves a named class to the top of its enclosing class."
5153 input Absyn.Path inClassName;
5154 input Absyn.Program inProgram;
5155 output Absyn.Program outProgram = inProgram;
5156 output Boolean outSuccess;
5157 protected
5158 Absyn.Path parent_cls;
5159 String cls_name;
5160 algorithm
5161 try
5162 ✗ if AbsynUtil.pathIsIdent(inClassName) then
5163 outProgram := match outProgram
5164 local
5165 list<Absyn.Class> classes;
5166 Absyn.Class cls;
5167
5168 case Absyn.PROGRAM()
5169 algorithm
5170 ✗ (classes, SOME(cls)) :=
5171 List.deleteMemberOnTrue(AbsynUtil.pathFirstIdent(inClassName),
5172 outProgram.classes, AbsynUtil.isClassNamed);
5173 ✗ outProgram.classes := cls :: classes;
5174 then
5175 outProgram;
5176 end match;
5177 else
5178 ✗ (parent_cls, Absyn.IDENT(cls_name)) := AbsynUtil.splitQualAndIdentPath(inClassName);
5179 ✗ outProgram := Interactive.transformPathedClassInProgram(parent_cls, inProgram,
5180 function moveClassToTopInClass(inName = cls_name));
5181 end if;
5182
5183 outSuccess := true;
5184 else
5185 outSuccess := false;
5186 end try;
5187 end moveClassToTop;
5188
5189 protected function moveClassToBottom
5190 "Moves a named class to the bottom of its enclosing class."
5191 input Absyn.Path inClassName;
5192 input Absyn.Program inProgram;
5193 output Absyn.Program outProgram = inProgram;
5194 output Boolean outSuccess;
5195 protected
5196 Absyn.Path parent_cls;
5197 String cls_name;
5198 algorithm
5199 try
5200 ✗ if AbsynUtil.pathIsIdent(inClassName) then
5201 outProgram := match outProgram
5202 local
5203 list<Absyn.Class> classes;
5204 Absyn.Class cls;
5205
5206 case Absyn.PROGRAM()
5207 algorithm
5208 ✗ (classes, SOME(cls)) :=
5209 List.deleteMemberOnTrue(AbsynUtil.pathFirstIdent(inClassName),
5210 outProgram.classes, AbsynUtil.isClassNamed);
5211 ✗ outProgram.classes := listAppend(classes, {cls});
5212 then
5213 outProgram;
5214 end match;
5215 else
5216 ✗ (parent_cls, Absyn.IDENT(cls_name)) := AbsynUtil.splitQualAndIdentPath(inClassName);
5217 ✗ outProgram := Interactive.transformPathedClassInProgram(parent_cls, inProgram,
5218 function moveClassToBottomInClass(inName = cls_name));
5219 end if;
5220
5221 outSuccess := true;
5222 else
5223 outSuccess := false;
5224 end try;
5225 end moveClassToBottom;
5226
5227 protected function moveClassInProgram
5228 "Moves a named class a certain offset within a program."
5229 input String inName;
5230 input Integer inOffset;
5231 input Absyn.Program inProgram;
5232 output Absyn.Program outProgram = inProgram;
5233 algorithm
5234 outProgram := match outProgram
5235 case Absyn.PROGRAM()
5236 algorithm
5237 ✗ outProgram.classes := moveClassInClassList(inName, inOffset, outProgram.classes);
5238 then
5239 outProgram;
5240 end match;
5241 end moveClassInProgram;
5242
5243 protected function moveClassInClassList
5244 "Moves a named class a certain offset within a list of classes. Fails if no
5245 class with the given name could be found."
5246 input String inName;
5247 input Integer inOffset;
5248 input list<Absyn.Class> inClasses;
5249 output list<Absyn.Class> outClasses;
5250 protected
5251 Absyn.Class cls;
5252 list<Absyn.Class> acc = {}, rest = inClasses;
5253 String name;
5254 Integer offset;
5255 algorithm
5256 // Move classes from rest to acc until we find the class.
5257 // This will intentionally fail if the class isn't found.
5258 ✗ while true loop
5259 ✗ (cls as Absyn.CLASS(name = name)) :: rest := rest;
5260
5261 ✗ if name == inName then
5262 break;
5263 else
5264 acc := cls :: acc;
5265 end if;
5266 end while;
5267
5268 ✗ if inOffset > 0 then
5269 // Clamp offset so we don't move outside the list.
5270 ✗ offset := min(inOffset, listLength(rest));
5271
5272 // Move 'offset' number of classes from rest to acc.
5273 ✗ for i in 1:offset loop
5274 ✗ acc := listHead(rest) :: acc;
5275 ✗ rest := listRest(rest);
5276 end for;
5277 else
5278 // Clamp offset so we don't move outside the list.
5279 ✗ offset := max(inOffset, -listLength(acc));
5280
5281 // Move 'offset' number of classes from acc to rest.
5282 ✗ for i in offset:-1 loop
5283 ✗ rest := listHead(acc) :: rest;
5284 ✗ acc := listRest(acc);
5285 end for;
5286 end if;
5287
5288 // Assemble the class list again with the class in the correct position.
5289 ✗ outClasses := List.append_reverse(acc, cls :: rest);
5290 end moveClassInClassList;
5291
5292 protected function moveClassInClass
5293 "Moves a named class a certain offset within another class. Only handles long
5294 class and class extends definitions, since there's no meaningful way of moving
5295 a class inside e.g. a short class definition. Fails if the class can't be
5296 found. An out of bounds offset is clamped."
5297 input String inName;
5298 input Integer inOffset;
5299 input Absyn.Class inClass;
5300 output Absyn.Class outClass;
5301 protected
5302 Absyn.ClassDef body;
5303 algorithm
5304 1 Absyn.CLASS(body = body) := inClass;
5305
5306 body := match body
5307 case Absyn.PARTS()
5308 algorithm
5309 1 body.classParts := moveClassInClassParts(inName, inOffset, body.classParts);
5310 then
5311 body;
5312
5313 case Absyn.CLASS_EXTENDS()
5314 algorithm
5315 ✗ body.parts := moveClassInClassParts(inName, inOffset, body.parts);
5316 then
5317 body;
5318
5319 end match;
5320
5321 1 outClass := AbsynUtil.setClassBody(inClass, body);
5322 end moveClassInClass;
5323
5324 protected function moveClassInClassParts
5325 input String inName;
5326 input Integer inOffset;
5327 input list<Absyn.ClassPart> inClassParts;
5328 output list<Absyn.ClassPart> outClassParts = inClassParts;
5329 protected
5330 Absyn.ClassPart part;
5331 list<Absyn.ClassPart> acc = {}, rest = inClassParts, parts;
5332 Option<Absyn.ElementItem> cls = NONE();
5333 Integer offset;
5334 Boolean is_public, is_empty;
5335 algorithm
5336 // Go through the parts until we find the one containing the named class.
5337 ✗ while true loop
5338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 part :: rest := rest;
5339 1 (part, cls, offset, is_public) := moveClassInClassPart(inName, inOffset, part);
5340
5341
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 if isSome(cls) then
5342 break;
5343 else
5344 acc := part :: acc;
5345 end if;
5346 end while;
5347
5348 1 is_empty := AbsynUtil.isEmptyClassPart(part);
5349 // Operate on either rest or acc depending on offset direction.
5350
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 parts := if offset > 0 then rest else acc;
5351
5352
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 if listEmpty(parts) and offset <> 0 then
5353 // No parts left but offset isn't 0, insert the class at the end.
5354 ✗ parts := moveClassInClassParts3(Util.getOption(cls), offset < 0, is_public, part, parts);
5355 else
5356 // Otherwise, keeps moving the class until it's in the correct part.
5357 1 parts := moveClassInClassParts2(Util.getOption(cls), offset, is_public, parts);
5358
5359
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if not is_empty then
5360 // Only add the part we moved the class from if it contains something.
5361 parts := part :: parts;
5362 end if;
5363 end if;
5364
5365
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if offset > 0 then
5366 rest := parts;
5367 else
5368 acc := parts;
5369 end if;
5370
5371 // If the part we moved the class from is empty, try to merge the surrounding
5372 // parts so that repeated moving don't fragment the class.
5373
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if is_empty and not listEmpty(rest) then
5374 ✗ part :: rest := rest;
5375 ✗ acc := mergeClassPartWithList(part, acc);
5376 end if;
5377
5378 1 outClassParts := List.append_reverse(acc, rest);
5379 end moveClassInClassParts;
5380
5381 protected function mergeClassPartWithList
5382 "Tries to merge the given class part with the first part in the list. If they
5383 are not the same type it just adds the part to the head of the list instead."
5384 input Absyn.ClassPart inClassPart;
5385 input list<Absyn.ClassPart> inClassParts;
5386 output list<Absyn.ClassPart> outClassParts;
5387 protected
5388 Absyn.ClassPart part;
5389 list<Absyn.ClassPart> rest;
5390 algorithm
5391 outClassParts := match (inClassPart, inClassParts)
5392 case (Absyn.PUBLIC(), (part as Absyn.PUBLIC()) :: rest)
5393 ✗ then Absyn.PUBLIC(listAppend(part.contents, inClassPart.contents)) :: rest;
5394 case (Absyn.PROTECTED(), (part as Absyn.PROTECTED()) :: rest)
5395 ✗ then Absyn.PROTECTED(listAppend(part.contents, inClassPart.contents)) :: rest;
5396 else inClassPart :: inClassParts;
5397 end match;
5398 end mergeClassPartWithList;
5399
5400 protected function moveClassInClassParts2
5401 "Helper function to moveClassInClassParts. Inserts the class into the correct
5402 class part."
5403 input Absyn.ElementItem inClass;
5404 input Integer inOffset;
5405 input Boolean inIsPublic;
5406 input list<Absyn.ClassPart> inClassParts;
5407 output list<Absyn.ClassPart> outClassParts;
5408 protected
5409 Absyn.ClassPart part;
5410 list<Absyn.ClassPart> rest = inClassParts, parts, acc = {};
5411 Integer offset = inOffset;
5412 Boolean moved;
5413 algorithm
5414 // Loop while we still have some offset to move the class.
5415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 while offset <> 0 loop
5416 ✗ part :: rest := rest;
5417 // Move the class through the next part.
5418 ✗ (parts, offset, moved) := moveClassInClassPart3(inClass, offset, inIsPublic, part);
5419
5420 ✗ if listEmpty(rest) and not moved then
5421 // We ran out of class parts, add the class at the end.
5422 ✗ acc := moveClassInClassParts3(inClass, inOffset > 0, inIsPublic, part, acc);
5423 ✗ break;
5424 elseif offset == 0 and not moved then
5425 // The offset is zero, but the class still hasn't been inserted anywhere.
5426 // This happens when the class was just moved outside the current part,
5427 // and should be inserted into the next one.
5428 // Add the parts we've just processed.
5429 ✗ acc := listAppend(parts, acc);
5430 // Add the class to the next part if it has the same protection, otherwise
5431 // create a new part for it.
5432 ✗ part :: rest := rest;
5433 ✗ acc := moveClassInClassParts3(inClass, inOffset > 0, inIsPublic, part, acc);
5434 ✗ break;
5435 end if;
5436
5437 ✗ acc := listAppend(if inOffset > 0 then parts else listReverse(parts), acc);
5438 end while;
5439
5440 1 outClassParts := List.append_reverse(acc, rest);
5441 end moveClassInClassParts2;
5442
5443 protected function moveClassInClassParts3
5444 "Helper function to moveClassInClassParts2. Inserts a class into a given class
5445 part if they have the same protection, or create a new part for the class
5446 otherwise. Then the part(s) are added to the given list of parts."
5447 input Absyn.ElementItem inClass;
5448 input Boolean inPositiveOffset;
5449 input Boolean inIsPublic;
5450 input Absyn.ClassPart inClassPart;
5451 input list<Absyn.ClassPart> inClassParts;
5452 output list<Absyn.ClassPart> outClassParts;
5453 algorithm
5454 outClassParts := match (inPositiveOffset, inIsPublic, inClassPart)
5455 case (true, true, Absyn.PUBLIC())
5456 ✗ then Absyn.PUBLIC(inClass :: inClassPart.contents) :: inClassParts;
5457 case (true, false, Absyn.PROTECTED())
5458 ✗ then Absyn.PROTECTED(inClass :: inClassPart.contents) :: inClassParts;
5459 case (false, true, Absyn.PUBLIC())
5460 ✗ then Absyn.PUBLIC(listAppend(inClassPart.contents, {inClass})) :: inClassParts;
5461 case (false, false, Absyn.PROTECTED())
5462 ✗ then Absyn.PROTECTED(listAppend(inClassPart.contents, {inClass})) :: inClassParts;
5463 case (_, true, _)
5464 ✗ then Absyn.PUBLIC({inClass}) :: inClassPart :: inClassParts;
5465 case (_, false, _)
5466 ✗ then Absyn.PROTECTED({inClass}) :: inClassPart :: inClassParts;
5467 end match;
5468 end moveClassInClassParts3;
5469
5470 protected function moveClassInClassPart
5471 "Moves a named class a certain offset within a single class part."
5472 input String inName;
5473 input Integer inOffset;
5474 input Absyn.ClassPart inClassPart;
5475 output Absyn.ClassPart outClassPart = inClassPart;
5476 output Option<Absyn.ElementItem> outClass;
5477 output Integer outRemainingOffset;
5478 output Boolean outIsPublic;
5479 protected
5480 list<Absyn.ElementItem> elements;
5481 algorithm
5482 (outClassPart, outClass, outRemainingOffset, outIsPublic) := match outClassPart
5483 case Absyn.PUBLIC()
5484 algorithm
5485 1 (elements, outClass, outRemainingOffset) :=
5486 moveClassInClassPart2(inName, inOffset, outClassPart.contents);
5487 1 outClassPart.contents := elements;
5488 1 then
5489 (outClassPart, outClass, outRemainingOffset, true);
5490
5491 case Absyn.PROTECTED()
5492 algorithm
5493 ✗ (elements, outClass, outRemainingOffset) :=
5494 moveClassInClassPart2(inName, inOffset, outClassPart.contents);
5495 ✗ outClassPart.contents := elements;
5496 ✗ then
5497 (outClassPart, outClass, outRemainingOffset, false);
5498
5499 else (outClassPart, NONE(), inOffset, false);
5500 end match;
5501 end moveClassInClassPart;
5502
5503 protected function moveClassInClassPart2
5504 "Helper function to moveClassInClassPart. Moves a named class a certain offset
5505 within a list of element items."
5506 input String inName;
5507 input Integer inOffset;
5508 input list<Absyn.ElementItem> inElements;
5509 output list<Absyn.ElementItem> outElements;
5510 output Option<Absyn.ElementItem> outClass = NONE();
5511 output Integer outRemainingOffset;
5512 protected
5513 Absyn.ElementItem e;
5514 list<Absyn.ElementItem> elements = inElements, acc = {};
5515 algorithm
5516 // Try to find an element item containing the class we're looking for.
5517
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 while not listEmpty(elements) loop
5518 2 e :: elements := elements;
5519
5520
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
2 if AbsynUtil.isElementItemClassNamed(inName, e) then
5521 // Found the class, exit the loop.
5522 outClass := SOME(e);
5523 1 break;
5524 else
5525 acc := e :: acc;
5526 end if;
5527 end while;
5528
5529 // No class found.
5530
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 if isNone(outClass) then
5531 outElements := inElements;
5532 ✗ outRemainingOffset := inOffset;
5533 ✗ return;
5534 end if;
5535
5536 // Try to move the class within the elements we have.
5537 1 (acc, elements, outRemainingOffset) :=
5538 moveClassInSplitClassPart(inOffset, acc, elements);
5539
5540 // Insert the class again if it was moved within this class part. Otherwise it needs
5541 // to be moved into another class part, which is handled by moveClassInClassParts.
5542
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if outRemainingOffset == 0 then
5543 2 elements := Util.getOption(outClass) :: elements;
5544 end if;
5545
5546 1 outElements := List.append_reverse(acc, elements);
5547 end moveClassInClassPart2;
5548
5549 protected function makeClassPart
5550 input list<Absyn.ElementItem> inElements;
5551 input Boolean inPublic;
5552 output Absyn.ClassPart outPart =
5553 if inPublic then Absyn.PUBLIC(inElements) else Absyn.PROTECTED(inElements);
5554 end makeClassPart;
5555
5556 protected function moveClassInClassPart3
5557 "Helper function to moveClassInClassParts2. Moves a class a certain offset in
5558 a given class part."
5559 input Absyn.ElementItem inClass;
5560 input Integer inOffset;
5561 input Boolean inIsPublic;
5562 input Absyn.ClassPart inClassPart;
5563 output list<Absyn.ClassPart> outClassParts;
5564 output Integer outRemainingOffset;
5565 output Boolean outMoved = false;
5566 protected
5567 Boolean same_part_type, reached_end;
5568 list<Absyn.ElementItem> elems_before, elems_after, elems;
5569 algorithm
5570 // Fetch the elements of the part, and remember if it has the same protection
5571 // as the class to be moved.
5572 (elems, same_part_type) := match inClassPart
5573 ✗ case Absyn.PUBLIC() then (inClassPart.contents, inIsPublic);
5574 ✗ case Absyn.PROTECTED() then (inClassPart.contents, not inIsPublic);
5575 end match;
5576
5577 // Use moveClassInSplitClassPart to shuffle elements.
5578 ✗ if inOffset > 0 then
5579 elems_before := {};
5580 ✗ elems_after := elems;
5581 else
5582 elems_before := elems;
5583 ✗ elems_after := {};
5584 end if;
5585
5586 ✗ (elems_before, elems_after, outRemainingOffset, reached_end) :=
5587 moveClassInSplitClassPart(inOffset, listReverse(elems_before), elems_after);
5588
5589 // No remaining offset, the class has been moved to where it should be.
5590 ✗ if outRemainingOffset == 0 then
5591 ✗ if same_part_type then
5592 // The class and the class part has the same protection, insert the class
5593 // into the part.
5594 ✗ elems := List.append_reverse(elems_before, inClass :: elems_after);
5595 ✗ outClassParts := {makeClassPart(elems, inIsPublic)};
5596 outMoved := true;
5597 elseif not reached_end then
5598 // If we did not reach the end, and the protection isn't the same, split
5599 // the class part into three potential parts, with the class in its own
5600 // part in the middle.
5601 ✗ outClassParts := if listEmpty(elems_before) then {} else
5602 {makeClassPart(listReverse(elems_before), not inIsPublic)};
5603 ✗ outClassParts := makeClassPart({inClass}, inIsPublic) :: outClassParts;
5604 ✗ if not listEmpty(elems_after) then
5605 ✗ outClassParts := makeClassPart(elems_after, not inIsPublic) :: outClassParts;
5606 end if;
5607 outMoved := true;
5608 else
5609 // Different protection, and we did reach the end. In that case the class
5610 // should be moved into the next part, if that part has the same
5611 // protection. We don't know that here, so we return the class part as it
5612 // is and let moveClassInClassParts2 sort it out.
5613 outClassParts := {inClassPart};
5614 end if;
5615 else
5616 outClassParts := {inClassPart};
5617 end if;
5618 end moveClassInClassPart3;
5619
5620 protected function moveClassInSplitClassPart
5621 "Takes two lists of element items and an offset. Moves elements from one list
5622 to the other until offset number of classes has been moved or the end in
5623 either direction has been reached."
5624 input Integer inOffset;
5625 input list<Absyn.ElementItem> inElementsBefore;
5626 input list<Absyn.ElementItem> inElementsAfter;
5627 output list<Absyn.ElementItem> outElementsBefore = inElementsBefore;
5628 output list<Absyn.ElementItem> outElementsAfter = inElementsAfter;
5629 output Integer outRemainingOffset = inOffset;
5630 output Boolean outReachedEnd;
5631 protected
5632 Absyn.ElementItem e;
5633 algorithm
5634
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if inOffset > 0 then
5635 // Positive offset, move elements from after to before.
5636 ✗ while outRemainingOffset > 0 loop
5637 ✗ if listEmpty(outElementsAfter) then // No more elements, we're done.
5638 break;
5639 else
5640 ✗ e :: outElementsAfter := outElementsAfter;
5641 outElementsBefore := e :: outElementsBefore;
5642
5643 // Decrease the offset for each class we move.
5644 ✗ if AbsynUtil.isElementItemClass(e) then
5645 ✗ outRemainingOffset := outRemainingOffset - 1;
5646 end if;
5647 end if;
5648 end while;
5649 ✗ outReachedEnd := listEmpty(outElementsAfter);
5650 else
5651 // Negative offset, move elements from before to after.
5652
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 while outRemainingOffset < 0 loop
5653
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if listEmpty(outElementsBefore) then // No more elements, we're done.
5654 break;
5655 else
5656 1 e :: outElementsBefore := outElementsBefore;
5657 outElementsAfter := e :: outElementsAfter;
5658
5659 // Increase the offset for each class we move.
5660
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if AbsynUtil.isElementItemClass(e) then
5661 1 outRemainingOffset := outRemainingOffset + 1;
5662 end if;
5663 end if;
5664 end while;
5665 1 outReachedEnd := listEmpty(outElementsBefore);
5666 end if;
5667 end moveClassInSplitClassPart;
5668
5669 protected function deleteClassInClassPart
5670 input String inName;
5671 input Absyn.ClassPart inClassPart;
5672 output Absyn.ClassPart outClassPart = inClassPart;
5673 output Option<Absyn.ElementItem> outClass;
5674 protected
5675 list<Absyn.ElementItem> elements;
5676 algorithm
5677 (outClassPart, outClass) := match outClassPart
5678 case Absyn.PUBLIC()
5679 algorithm
5680 ✗ (elements, outClass) := List.deleteMemberOnTrue(inName,
5681 outClassPart.contents, AbsynUtil.isElementItemClassNamed);
5682 ✗ outClassPart.contents := elements;
5683 ✗ then
5684 (outClassPart, outClass);
5685
5686 case Absyn.PROTECTED()
5687 algorithm
5688 ✗ (elements, outClass) := List.deleteMemberOnTrue(inName,
5689 outClassPart.contents, AbsynUtil.isElementItemClassNamed);
5690 ✗ outClassPart.contents := elements;
5691 ✗ then
5692 (outClassPart, outClass);
5693
5694 else (outClassPart, NONE());
5695 end match;
5696 end deleteClassInClassPart;
5697
5698 protected function moveClassToTopInClass
5699 input String inName;
5700 input Absyn.Class inClass;
5701 output Absyn.Class outClass;
5702 protected
5703 Absyn.ClassDef body;
5704 algorithm
5705 ✗ Absyn.CLASS(body = body) := inClass;
5706
5707 body := match body
5708 case Absyn.PARTS()
5709 algorithm
5710 ✗ body.classParts := moveClassToTopInClassParts(inName, body.classParts);
5711 then
5712 body;
5713
5714 case Absyn.CLASS_EXTENDS()
5715 algorithm
5716 ✗ body.parts := moveClassToTopInClassParts(inName, body.parts);
5717 then
5718 body;
5719
5720 end match;
5721
5722 ✗ outClass := AbsynUtil.setClassBody(inClass, body);
5723 end moveClassToTopInClass;
5724
5725 protected function moveClassToTopInClassParts
5726 input String inName;
5727 input list<Absyn.ClassPart> inClassParts;
5728 output list<Absyn.ClassPart> outClassParts;
5729 protected
5730 Absyn.ClassPart part, first;
5731 list<Absyn.ClassPart> acc = {}, rest = inClassParts;
5732 Option<Absyn.ElementItem> ocls;
5733 Absyn.ElementItem cls;
5734 algorithm
5735 ✗ while true loop
5736 ✗ part :: rest := rest;
5737 ✗ (part, ocls) := deleteClassInClassPart(inName, part);
5738
5739 ✗ if isSome(ocls) then
5740 // Remove the part if it's now empty and not the only part.
5741 ✗ if not AbsynUtil.isEmptyClassPart(part) or listEmpty(acc) or listEmpty(rest) then
5742 rest := part :: rest;
5743 end if;
5744 ✗ outClassParts := List.append_reverse(acc, rest);
5745 break;
5746 else
5747 acc := part :: acc;
5748 end if;
5749 end while;
5750
5751 ✗ SOME(cls) := ocls;
5752 ✗ first :: rest := outClassParts;
5753
5754 outClassParts := match (first, part)
5755 case (Absyn.PUBLIC(), Absyn.PUBLIC())
5756 algorithm
5757 ✗ first.contents := cls :: first.contents;
5758 then
5759 first :: rest;
5760 case (Absyn.PROTECTED(), Absyn.PROTECTED())
5761 algorithm
5762 ✗ first.contents := cls :: first.contents;
5763 then
5764 first :: rest;
5765 ✗ case (_, Absyn.PUBLIC()) then Absyn.PUBLIC({cls}) :: first :: rest;
5766 ✗ case (_, Absyn.PROTECTED()) then Absyn.PROTECTED({cls}) :: first :: rest;
5767 end match;
5768 end moveClassToTopInClassParts;
5769
5770 protected function moveClassToBottomInClass
5771 input String inName;
5772 input Absyn.Class inClass;
5773 output Absyn.Class outClass;
5774 protected
5775 Absyn.ClassDef body;
5776 algorithm
5777 ✗ Absyn.CLASS(body = body) := inClass;
5778
5779 body := match body
5780 case Absyn.PARTS()
5781 algorithm
5782 ✗ body.classParts := moveClassToBottomInClassParts(inName, body.classParts);
5783 then
5784 body;
5785
5786 case Absyn.CLASS_EXTENDS()
5787 algorithm
5788 ✗ body.parts := moveClassToBottomInClassParts(inName, body.parts);
5789 then
5790 body;
5791
5792 end match;
5793
5794 ✗ outClass := AbsynUtil.setClassBody(inClass, body);
5795 end moveClassToBottomInClass;
5796
5797 protected function moveClassToBottomInClassParts
5798 input String inName;
5799 input list<Absyn.ClassPart> inClassParts;
5800 output list<Absyn.ClassPart> outClassParts;
5801 protected
5802 Absyn.ClassPart part, last;
5803 list<Absyn.ClassPart> acc = {}, rest = inClassParts;
5804 Option<Absyn.ElementItem> ocls;
5805 Absyn.ElementItem cls;
5806 algorithm
5807 ✗ while true loop
5808 ✗ part :: rest := rest;
5809 ✗ (part, ocls) := deleteClassInClassPart(inName, part);
5810
5811 ✗ if isSome(ocls) then
5812 break;
5813 else
5814 acc := part :: acc;
5815 end if;
5816 end while;
5817
5818 ✗ SOME(cls) := ocls;
5819
5820 // Remove the part if it's empty and not the only remaining part.
5821 ✗ if not AbsynUtil.isEmptyClassPart(part) or listEmpty(rest) then
5822 rest := part :: rest;
5823 end if;
5824
5825 ✗ last :: rest := listReverse(rest);
5826
5827 rest := match (last, part)
5828 case (Absyn.PUBLIC(), Absyn.PUBLIC())
5829 algorithm
5830 ✗ last.contents := listAppend(last.contents, {cls});
5831 then
5832 last :: rest;
5833 case (Absyn.PROTECTED(), Absyn.PROTECTED())
5834 algorithm
5835 ✗ last.contents := listAppend(last.contents, {cls});
5836 then
5837 last :: rest;
5838 ✗ case (_, Absyn.PUBLIC()) then Absyn.PUBLIC({cls}) :: last :: rest;
5839 ✗ case (_, Absyn.PROTECTED()) then Absyn.PROTECTED({cls}) :: last :: rest;
5840 end match;
5841
5842 ✗ outClassParts := List.append_reverse(acc, listReverse(rest));
5843 end moveClassToBottomInClassParts;
5844
5845 protected function copyClass
5846 input Absyn.Class inClass;
5847 input String inName;
5848 input Absyn.Within inWithin;
5849 input Absyn.Path inClassPath;
5850 input Absyn.Program inProg;
5851 output Absyn.Program outProg;
5852 protected
5853 Absyn.Class cls;
5854 String orig_file, dst_path;
5855 algorithm
5856 Absyn.CLASS(info = SOURCEINFO(fileName = orig_file)) := inClass;
5857
5858 dst_path := match inWithin
5859 // Destination is top scope, put the copy in a new file.
5860 case Absyn.TOP() then "<interactive>";
5861
5862 // Destination is within another class, put the copy in the same file as the
5863 // destination class.
5864 case Absyn.WITHIN()
5865 algorithm
5866 4 Absyn.CLASS(info = SOURCEINFO(fileName = dst_path)) :=
5867 ProgramUtil.getPathedClassInProgram(inWithin.path, inProg);
5868 then
5869 dst_path;
5870
5871 end match;
5872
5873 // Update the paths in the class to reflect the new location.
5874 6 cls := NFApi.updateMovedClassPaths(inClass, inClassPath, inWithin);
5875
5876 // Replace the filename of each element with the new path.
5877 6 cls := moveClassInfo(cls, dst_path);
5878
5879 // Change the name of the class and put it in as a copy in the program.
5880 6 cls := AbsynUtil.setClassName(cls, inName);
5881 6 outProg := ProgramUtil.updateProgram(Absyn.PROGRAM({cls}, inWithin), inProg);
5882 end copyClass;
5883
5884 protected function moveSourceInfo
5885 input SourceInfo inInfo;
5886 input String dstPath;
5887 output SourceInfo outInfo = inInfo;
5888 algorithm
5889 () := match outInfo
5890
5891 case SOURCEINFO()
5892 algorithm
5893 28 outInfo.fileName := dstPath;
5894 28 outInfo.isReadOnly := false;
5895 then
5896 ();
5897
5898 end match;
5899 end moveSourceInfo;
5900
5901 protected function moveClassInfo
5902 input Absyn.Class inClass;
5903 input String dstPath;
5904 output Absyn.Class outClass = inClass;
5905 protected
5906 SourceInfo info;
5907 algorithm
5908 () := match outClass
5909 case Absyn.CLASS(info = info as SOURCEINFO())
5910 algorithm
5911 8 outClass.body := moveClassDefInfo(outClass.body, dstPath);
5912 8 outClass.info := moveSourceInfo(info, dstPath);
5913 then
5914 ();
5915 end match;
5916 end moveClassInfo;
5917
5918 protected function moveClassDefInfo
5919 input Absyn.ClassDef inClassDef;
5920 input String dstPath;
5921 output Absyn.ClassDef outClassDef = inClassDef;
5922 algorithm
5923 () := match outClassDef
5924 case Absyn.PARTS()
5925 algorithm
5926
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 6 times.
20 outClassDef.classParts := list(moveClassPartInfo(cp, dstPath)
5927 for cp in outClassDef.classParts);
5928
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
12 outClassDef.ann := list(moveAnnotationInfo(a, dstPath)
5929 for a in outClassDef.ann);
5930 then
5931 ();
5932
5933 case Absyn.DERIVED()
5934 algorithm
5935
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
4 outClassDef.arguments := list(moveElementArgInfo(e, dstPath)
5936 for e in outClassDef.arguments);
5937 2 outClassDef.comment := moveCommentInfo(outClassDef.comment, dstPath);
5938 then
5939 ();
5940
5941 case Absyn.ENUMERATION()
5942 algorithm
5943 ✗ outClassDef.comment := moveCommentInfo(outClassDef.comment, dstPath);
5944 then
5945 ();
5946
5947 case Absyn.OVERLOAD()
5948 algorithm
5949 ✗ outClassDef.comment := moveCommentInfo(outClassDef.comment, dstPath);
5950 then
5951 ();
5952
5953 case Absyn.CLASS_EXTENDS()
5954 algorithm
5955 ✗ outClassDef.modifications := list(moveElementArgInfo(e, dstPath)
5956 for e in outClassDef.modifications);
5957 ✗ outClassDef.parts := list(moveClassPartInfo(cp, dstPath)
5958 for cp in outClassDef.parts);
5959 ✗ outClassDef.ann := list(moveAnnotationInfo(a, dstPath)
5960 for a in outClassDef.ann);
5961 then
5962 ();
5963
5964 case Absyn.PDER()
5965 algorithm
5966 ✗ outClassDef.comment := moveCommentInfo(outClassDef.comment, dstPath);
5967 then
5968 ();
5969
5970 else ();
5971 end match;
5972 end moveClassDefInfo;
5973
5974 protected function moveClassPartInfo
5975 input Absyn.ClassPart inPart;
5976 input String dstPath;
5977 output Absyn.ClassPart outPart;
5978 algorithm
5979 outPart := match inPart
5980 local
5981 list<Absyn.ElementItem> el;
5982 list<Absyn.EquationItem> eq;
5983 list<Absyn.AlgorithmItem> alg;
5984 Absyn.ExternalDecl ext;
5985 Option<Absyn.Annotation> ann;
5986
5987 case Absyn.PUBLIC(el)
5988
4/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 6 times.
17 then Absyn.PUBLIC(list(moveElementItemInfo(e, dstPath) for e in el));
5989
5990 case Absyn.PROTECTED(el)
5991 ✗ then Absyn.PROTECTED(list(moveElementItemInfo(e, dstPath) for e in el));
5992
5993 case Absyn.EQUATIONS(eq)
5994
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
2 then Absyn.EQUATIONS(list(moveEquationItemInfo(e, dstPath) for e in eq));
5995
5996 case Absyn.INITIALEQUATIONS(eq)
5997 ✗ then Absyn.INITIALEQUATIONS(list(moveEquationItemInfo(e, dstPath) for e in eq));
5998
5999 case Absyn.ALGORITHMS(alg)
6000
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
2 then Absyn.ALGORITHMS(list(moveAlgorithmItemInfo(e, dstPath) for e in alg));
6001
6002 case Absyn.INITIALALGORITHMS(alg)
6003 ✗ then Absyn.INITIALALGORITHMS(list(moveAlgorithmItemInfo(e, dstPath) for e in alg));
6004
6005 case Absyn.EXTERNAL(ext, ann)
6006 algorithm
6007 ✗ ext := moveExternalDeclInfo(ext, dstPath);
6008 ✗ ann := moveAnnotationOptInfo(ann, dstPath);
6009 ✗ then
6010 Absyn.EXTERNAL(ext, ann);
6011
6012 else inPart;
6013 end match;
6014 end moveClassPartInfo;
6015
6016 protected function moveAnnotationOptInfo
6017 input Option<Absyn.Annotation> inAnnotation;
6018 input String dstPath;
6019 output Option<Absyn.Annotation> outAnnotation;
6020 algorithm
6021 outAnnotation := match inAnnotation
6022 local
6023 Absyn.Annotation a;
6024
6025 ✗ case SOME(a) then SOME(moveAnnotationInfo(a, dstPath));
6026 else inAnnotation;
6027 end match;
6028 end moveAnnotationOptInfo;
6029
6030 protected function moveAnnotationInfo
6031 input Absyn.Annotation inAnnotation;
6032 input String dstPath;
6033 output Absyn.Annotation outAnnotation = inAnnotation;
6034 algorithm
6035
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 time.
3 outAnnotation.elementArgs := list(moveElementArgInfo(e, dstPath) for e in outAnnotation.elementArgs);
6036 end moveAnnotationInfo;
6037
6038 protected function moveElementItemInfo
6039 input Absyn.ElementItem inElement;
6040 input String dstPath;
6041 output Absyn.ElementItem outElement;
6042 algorithm
6043 outElement := match inElement
6044 case Absyn.ELEMENTITEM()
6045 11 then Absyn.ELEMENTITEM(moveElementInfo(inElement.element, dstPath));
6046 else inElement;
6047 end match;
6048 end moveElementItemInfo;
6049
6050 protected function moveElementInfo
6051 input Absyn.Element inElement;
6052 input String dstPath;
6053 output Absyn.Element outElement = inElement;
6054 algorithm
6055 () := match outElement
6056 case Absyn.ELEMENT()
6057 algorithm
6058 11 outElement.specification := moveElementSpecInfo(outElement.specification, dstPath);
6059 11 outElement.constrainClass := moveConstrainClassInfo(outElement.constrainClass, dstPath);
6060 11 outElement.info := moveSourceInfo(outElement.info, dstPath);
6061 then
6062 ();
6063
6064 case Absyn.TEXT()
6065 algorithm
6066 ✗ outElement.info := moveSourceInfo(outElement.info, dstPath);
6067 then
6068 ();
6069
6070 else ();
6071 end match;
6072 end moveElementInfo;
6073
6074 protected function moveElementArgInfo
6075 input Absyn.ElementArg inArg;
6076 input String dstPath;
6077 output Absyn.ElementArg outArg = inArg;
6078 algorithm
6079 () := match outArg
6080 case Absyn.MODIFICATION()
6081 algorithm
6082 2 outArg.modification := moveModificationInfo(outArg.modification, dstPath);
6083 2 outArg.info := moveSourceInfo(outArg.info, dstPath);
6084 then
6085 ();
6086
6087 case Absyn.REDECLARATION()
6088 algorithm
6089 ✗ outArg.elementSpec := moveElementSpecInfo(outArg.elementSpec, dstPath);
6090 ✗ outArg.constrainClass := moveConstrainClassInfo(outArg.constrainClass, dstPath);
6091 ✗ outArg.info := moveSourceInfo(outArg.info, dstPath);
6092 then
6093 ();
6094
6095 else ();
6096 end match;
6097 end moveElementArgInfo;
6098
6099 protected function moveModificationInfo
6100 input Option<Absyn.Modification> inMod;
6101 input String dstPath;
6102 output Option<Absyn.Modification> outMod;
6103 algorithm
6104 outMod := match inMod
6105 local
6106 list<Absyn.ElementArg> el;
6107 Absyn.EqMod eq;
6108
6109 case SOME(Absyn.CLASSMOD(el, eq))
6110 algorithm
6111
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 6 times.
7 el := list(moveElementArgInfo(e, dstPath) for e in el);
6112 6 eq := moveEqModInfo(eq, dstPath);
6113 6 then
6114 SOME(Absyn.CLASSMOD(el, eq));
6115
6116 else inMod;
6117 end match;
6118 end moveModificationInfo;
6119
6120 protected function moveEqModInfo
6121 input Absyn.EqMod inEqMod;
6122 input String dstPath;
6123 output Absyn.EqMod outEqMod;
6124 algorithm
6125 outEqMod := match inEqMod
6126 case Absyn.EQMOD()
6127 5 then Absyn.EQMOD(inEqMod.exp, moveSourceInfo(inEqMod.info, dstPath));
6128 else inEqMod;
6129 end match;
6130 end moveEqModInfo;
6131
6132 protected function moveConstrainClassInfo
6133 input Option<Absyn.ConstrainClass> inCC;
6134 input String dstPath;
6135 output Option<Absyn.ConstrainClass> outCC;
6136 algorithm
6137 outCC := match inCC
6138 local
6139 Absyn.ElementSpec spec;
6140 Option<Absyn.Comment> cmt;
6141
6142 case SOME(Absyn.CONSTRAINCLASS(spec, cmt))
6143 algorithm
6144 ✗ spec := moveElementSpecInfo(spec, dstPath);
6145 ✗ cmt := moveCommentInfo(cmt, dstPath);
6146 ✗ then
6147 SOME(Absyn.CONSTRAINCLASS(spec, cmt));
6148
6149 else inCC;
6150 end match;
6151 end moveConstrainClassInfo;
6152
6153 protected function moveCommentInfo
6154 input Option<Absyn.Comment> inComment;
6155 input String dstPath;
6156 output Option<Absyn.Comment> outComment;
6157 algorithm
6158 outComment := match inComment
6159 local
6160 Absyn.Annotation a;
6161 Option<String> c;
6162
6163 case SOME(Absyn.COMMENT(SOME(a), c))
6164 algorithm
6165 1 a := moveAnnotationInfo(a, dstPath);
6166 1 then
6167 SOME(Absyn.COMMENT(SOME(a), c));
6168
6169 else inComment;
6170 end match;
6171 end moveCommentInfo;
6172
6173 protected function moveEquationItemInfo
6174 input Absyn.EquationItem inEquation;
6175 input String dstPath;
6176 output Absyn.EquationItem outEquation;
6177 algorithm
6178 outEquation := match inEquation
6179 local
6180 Absyn.Equation eq;
6181 Option<Absyn.Comment> cmt;
6182 SourceInfo info;
6183
6184 case Absyn.EQUATIONITEM(eq, cmt, info)
6185 algorithm
6186 1 cmt := moveCommentInfo(cmt, dstPath);
6187 1 info := moveSourceInfo(info, dstPath);
6188 1 then
6189 Absyn.EQUATIONITEM(eq, cmt, info);
6190
6191 else inEquation;
6192 end match;
6193 end moveEquationItemInfo;
6194
6195 protected function moveAlgorithmItemInfo
6196 input Absyn.AlgorithmItem inAlgorithm;
6197 input String dstPath;
6198 output Absyn.AlgorithmItem outAlgorithm;
6199 algorithm
6200 outAlgorithm := match inAlgorithm
6201 local
6202 Absyn.Algorithm alg;
6203 Option<Absyn.Comment> cmt;
6204 SourceInfo info;
6205
6206 case Absyn.ALGORITHMITEM(alg, cmt, info)
6207 algorithm
6208 1 cmt := moveCommentInfo(cmt, dstPath);
6209 1 info := moveSourceInfo(info, dstPath);
6210 1 then
6211 Absyn.ALGORITHMITEM(alg, cmt, info);
6212
6213 else inAlgorithm;
6214 end match;
6215 end moveAlgorithmItemInfo;
6216
6217 protected function moveElementSpecInfo
6218 input Absyn.ElementSpec inSpec;
6219 input String dstPath;
6220 output Absyn.ElementSpec outSpec = inSpec;
6221 algorithm
6222 () := match outSpec
6223 case Absyn.CLASSDEF()
6224 algorithm
6225 2 outSpec.class_ := moveClassInfo(outSpec.class_, dstPath);
6226 then
6227 ();
6228
6229 case Absyn.EXTENDS()
6230 algorithm
6231 ✗ outSpec.elementArg := list(moveElementArgInfo(e, dstPath)
6232 for e in outSpec.elementArg);
6233 ✗ outSpec.annotationOpt := moveAnnotationOptInfo(outSpec.annotationOpt, dstPath);
6234 then
6235 ();
6236
6237 case Absyn.IMPORT()
6238 algorithm
6239 ✗ outSpec.comment := moveCommentInfo(outSpec.comment, dstPath);
6240 ✗ outSpec.info := moveSourceInfo(outSpec.info, dstPath);
6241 then
6242 ();
6243
6244 case Absyn.COMPONENTS()
6245 algorithm
6246
4/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9 times.
27 outSpec.components := list(moveComponentItemInfo(c, dstPath)
6247 for c in outSpec.components);
6248 then
6249 ();
6250
6251 else ();
6252 end match;
6253 end moveElementSpecInfo;
6254
6255 protected function moveComponentItemInfo
6256 input Absyn.ComponentItem inComponent;
6257 input String dstPath;
6258 output Absyn.ComponentItem outComponent;
6259 protected
6260 Absyn.Component comp;
6261 Option<Absyn.ComponentCondition> cond;
6262 Option<Absyn.Comment> cmt;
6263 algorithm
6264 9 Absyn.COMPONENTITEM(comp, cond, cmt) := inComponent;
6265 9 comp := moveComponentInfo(comp, dstPath);
6266 9 cmt := moveCommentInfo(cmt, dstPath);
6267 9 outComponent := Absyn.COMPONENTITEM(comp, cond, cmt);
6268 end moveComponentItemInfo;
6269
6270 protected function moveComponentInfo
6271 input Absyn.Component inComponent;
6272 input String dstPath;
6273 output Absyn.Component outComponent = inComponent;
6274 algorithm
6275 9 outComponent.modification := moveModificationInfo(outComponent.modification, dstPath);
6276 end moveComponentInfo;
6277
6278 protected function moveExternalDeclInfo
6279 input Absyn.ExternalDecl inExtDecl;
6280 input String dstPath;
6281 output Absyn.ExternalDecl outExtDecl = inExtDecl;
6282 algorithm
6283 ✗ outExtDecl.annotation_ := moveAnnotationOptInfo(outExtDecl.annotation_, dstPath);
6284 end moveExternalDeclInfo;
6285
6286 protected function buildModel "translates and builds the model by running compiler script on the generated makefile"
6287 input FCore.Cache inCache;
6288 input FCore.Graph inEnv;
6289 input list<Values.Value> inValues;
6290 input Absyn.Msg inMsg;
6291 output Boolean success=false;
6292 output FCore.Cache outCache;
6293 output String compileDir;
6294 output String outString1 "className";
6295 output String outString2 "method";
6296 output String outputFormat_str;
6297 output String outInitFileName "initFileName";
6298 output String outSimFlags;
6299 output list<tuple<String,Values.Value>> resultValues;
6300 output list<Values.Value> outArgs;
6301 output list<String> outLibsAndLibDirs;
6302 algorithm
6303 (outCache,compileDir,outString1,outString2,outputFormat_str,outInitFileName,outSimFlags,resultValues,outArgs,outLibsAndLibDirs):=
6304 matchcontinue (inCache, inEnv, inValues)
6305 local
6306 list<String> libsAndLibDirs;
6307 String file_dir,init_filename,method_str,filenameprefix,simflags;
6308 Absyn.Path classname;
6309 Real timeCompile;
6310 FCore.Graph env;
6311 SimCode.SimulationSettings simSettings;
6312 Values.Value method,outputFormat;
6313 list<Values.Value> vals, values;
6314 FCore.Cache cache;
6315 Option<Absyn.Modification> simflags_mod;
6316
6317 // compile the model
6318 case (cache, env, vals)
6319 algorithm
6320 // buildModel expects these arguments:
6321 // className, startTime, stopTime, numberOfIntervals, tolerance, method, fileNamePrefix,
6322 // options, outputFormat, variableFilter, cflags, simflags
6323 1160 values := vals;
6324
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1160 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1160 times.
1160 (Values.CODE(Absyn.C_TYPENAME(classname)),vals) := getListFirstShowError(vals, "while retrieving the className (1 arg) from the buildModel arguments");
6325 1160 (_,vals) := getListFirstShowError(vals, "while retrieving the startTime (2 arg) from the buildModel arguments");
6326 1160 (_,vals) := getListFirstShowError(vals, "while retrieving the stopTime (3 arg) from the buildModel arguments");
6327 1160 (_,vals) := getListFirstShowError(vals, "while retrieving the numberOfIntervals (4 arg) from the buildModel arguments");
6328 1160 (_,vals) := getListFirstShowError(vals, "while retrieving the tolerance (5 arg) from the buildModel arguments");
6329 1160 (_,vals) := getListFirstShowError(vals, "while retrieving the method (6 arg) from the buildModel arguments");
6330
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1160 times.
1160 (Values.STRING(filenameprefix),vals) := getListFirstShowError(vals, "while retreaving the fileNamePrefix (7 arg) from the buildModel arguments");
6331
6332
6333 1160 (_,vals) := getListFirstShowError(vals, "while retrieving the options (8 arg) from the buildModel arguments");
6334 1160 (_,vals) := getListFirstShowError(vals, "while retrieving the outputFormat (9 arg) from the buildModel arguments");
6335 1160 (_,vals) := getListFirstShowError(vals, "while retrieving the variableFilter (10 arg) from the buildModel arguments");
6336 1160 (_,vals) := getListFirstShowError(vals, "while retrieving the cflags (11 arg) from the buildModel arguments");
6337
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1160 times.
1160 (Values.STRING(simflags),vals) := getListFirstShowError(vals, "while retrieving the simflags (12 arg) from the buildModel arguments");
6338
6339 1160 Error.clearMessages() "Clear messages";
6340
6341 // If simflags is empty and --ignoreSimulationFlagsAnnotation isn't used,
6342 // use the __OpenModelica_simulationFlags annotation in the class to be simulated.
6343
3/4
✓ Branch 0 taken 815 times.
✓ Branch 1 taken 345 times.
✓ Branch 3 taken 815 times.
✗ Branch 4 not taken.
1160 if stringEmpty(simflags) and not Flags.getConfigBool(Flags.IGNORE_SIMULATION_FLAGS_ANNOTATION) then
6344 815 loadProgram(classname);
6345 815 simflags_mod := ProgramUtil.getNamedAnnotationExp(classname, SymbolTable.getAbsyn(),
6346 Absyn.IDENT("__OpenModelica_simulationFlags"), SOME(NONE()), Util.id);
6347 815 simflags := formatSimulationFlagsString(simflags_mod);
6348
6349
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 813 times.
815 if not stringEmpty(simflags) then
6350 2 values := List.replaceAt(Values.STRING(simflags), 12, values);
6351 end if;
6352 end if;
6353
6354 1160 compileDir := System.pwd() + Autoconf.pathDelimiter;
6355 1160 (cache,simSettings) := calculateSimulationSettings(cache, values);
6356 1160 SimCode.SIMULATION_SETTINGS(method = method_str, outputFormat = outputFormat_str) := simSettings;
6357
6358 1160 (success,cache,libsAndLibDirs,file_dir,resultValues) := translateModel(cache,env, classname, filenameprefix, true, true, SOME(simSettings));
6359 //cname_str = AbsynUtil.pathString(classname);
6360 //SimCodeUtil.generateInitData(indexed_dlow_1, classname, filenameprefix, init_filename,
6361 // starttime_r, stoptime_r, interval_r, tolerance_r, method_str,options_str,outputFormat_str);
6362
6363 1144 System.realtimeTick(ClockIndexes.RT_CLOCK_BUILD_MODEL);
6364 1144 init_filename := filenameprefix + "_init.xml"; //a hack ? should be at one place somewhere
6365 //win1 = getWithinStatement(classname);
6366
6367
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1144 times.
1144 if Flags.isSet(Flags.DYN_LOAD) then
6368 ✗ Debug.traceln("buildModel: about to compile model " + filenameprefix + ", " + file_dir);
6369 end if;
6370
1/2
✓ Branch 0 taken 1144 times.
✗ Branch 1 not taken.
1144 if success then
6371 try
6372 // The wasm-jit target produced the model WebAssembly module during
6373 // translateModel and runs it in-process at simulate time, so there
6374 // is no C executable to compile/link here. Instead, force the JIT
6375 // compile of the model's wasm modules now so its cost is attributed
6376 // to timeCompile (this clock) rather than leaking into
6377 // timeSimulation at runSimulation.
6378
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1144 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
1144 if Config.simCodeTarget() == "wasm-jit" then
6379 ✗ CodegenWasmJit.finishCompile(filenameprefix);
6380 elseif Config.simCodeTarget() == "wasm" then
6381 // The standalone module was already produced in emitStandalone;
6382 // there is nothing to compile/link here.
6383 else
6384 1144 CevalScript.compileModel(filenameprefix, libsAndLibDirs);
6385 end if;
6386 else
6387 success := false;
6388 end try;
6389 1144 timeCompile := System.realtimeTock(ClockIndexes.RT_CLOCK_BUILD_MODEL);
6390 else
6391 timeCompile := 0.0;
6392 end if;
6393
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1144 times.
1144 if Flags.isSet(Flags.DYN_LOAD) then
6394 ✗ Debug.trace("buildModel: Compiling done.\n");
6395 end if;
6396 1144 resultValues := ("timeCompile",Values.REAL(timeCompile)) :: resultValues;
6397
1/2
✓ Branch 0 taken 1144 times.
✗ Branch 1 not taken.
1144 then
6398 (cache,compileDir,filenameprefix,method_str,outputFormat_str,init_filename,simflags,resultValues,values,libsAndLibDirs);
6399
6400 // failure
6401 else
6402 algorithm
6403 16 Error.assertion(listLength(inValues) == 12, "buildModel failure, length = " + intString(listLength(inValues)), Absyn.dummyInfo);
6404 16 then fail();
6405 end matchcontinue;
6406 end buildModel;
6407
6408 function formatSimulationFlagsString
6409 "Formats a modification in the format expected by the simflags argument to buildModel."
6410 input Option<Absyn.Modification> mod;
6411 output String str;
6412 algorithm
6413 str := match mod
6414 local
6415 list<Absyn.ElementArg> args;
6416
6417 case SOME(Absyn.CLASSMOD(elementArgLst = args))
6418 2 then List.toStringCustom(args, formatSimulationFlagString, "", "-", " -", "", false);
6419
6420 else "";
6421 end match;
6422 end formatSimulationFlagsString;
6423
6424 function formatSimulationFlagString
6425 input Absyn.ElementArg arg;
6426 output String str;
6427 algorithm
6428 str := match arg
6429 local
6430 Absyn.Exp exp;
6431
6432 case Absyn.ElementArg.MODIFICATION(modification =
6433 SOME(Absyn.Modification.CLASSMOD(eqMod = Absyn.EqMod.EQMOD(exp = exp))))
6434 then
6435 match exp
6436 1 case Absyn.STRING("()") then AbsynUtil.pathString(arg.path);
6437 1 else AbsynUtil.pathString(arg.path) + "=" + Dump.printExpStr(exp);
6438 end match;
6439
6440 case Absyn.ElementArg.MODIFICATION()
6441 ✗ then AbsynUtil.pathString(arg.path);
6442
6443 end match;
6444 end formatSimulationFlagString;
6445
6446 protected function createSimulationResultFromcallModelExecutable
6447 "This function calls the compiled simulation executable."
6448 input Boolean buildSuccess;
6449 input Integer callRet;
6450 input Real timeTotal;
6451 input Real timeSimulation;
6452 input list<tuple<String,Values.Value>> resultValues;
6453 input FCore.Cache inCache;
6454 input Absyn.Path className;
6455 input list<Values.Value> inVals;
6456 input String result_file;
6457 input String logFile;
6458 output FCore.Cache outCache;
6459 output Values.Value outValue;
6460 algorithm
6461 (outCache,outValue) := matchcontinue (buildSuccess,callRet)
6462 local
6463 String res,str;
6464 Values.Value simValue;
6465
6466 case (false,_)
6467 algorithm
6468 2 simValue := createSimulationResult(
6469 result_file,
6470 simOptionsAsString(inVals),
6471 "Failed to build model: " + AbsynUtil.pathString(className),
6472 ("timeTotal", Values.REAL(timeTotal)) ::
6473 ("timeSimulation", Values.REAL(timeSimulation)) ::
6474 resultValues);
6475 then (inCache,simValue);
6476
6477 case (_,0)
6478 algorithm
6479 2316 simValue := createSimulationResult(
6480 result_file,
6481 simOptionsAsString(inVals),
6482 System.readFile(logFile),
6483 ("timeTotal", Values.REAL(timeTotal)) ::
6484 ("timeSimulation", Values.REAL(timeSimulation)) ::
6485 resultValues);
6486 1158 SymbolTable.addVar(
6487 DAE.CREF_IDENT("currentSimulationResult", DAE.T_STRING_DEFAULT, {}),
6488 Values.STRING(result_file), FGraph.empty());
6489 then
6490 (inCache,simValue);
6491 else
6492 algorithm
6493
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 res := if System.regularFileExists(logFile) then System.readFile(logFile) else (logFile + " does not exist");
6494 24 str := AbsynUtil.pathString(className);
6495 24 res := stringAppendList({"Simulation execution failed for model: ", str, "\n", res});
6496 48 simValue := createSimulationResult("", simOptionsAsString(inVals), res,
6497 ("timeTotal", Values.REAL(timeTotal)) ::
6498 ("timeSimulation", Values.REAL(timeSimulation)) ::
6499 resultValues);
6500 then
6501 (inCache,simValue);
6502 end matchcontinue;
6503 end createSimulationResultFromcallModelExecutable;
6504
6505
6506
6507 public function checkModel " checks a model and returns number of variables and equations"
6508 input output FCore.Cache cache;
6509 input FCore.Graph env;
6510 input Absyn.Path className;
6511 input Absyn.Msg inMsg;
6512 output Values.Value outValue;
6513 algorithm
6514 outValue := matchcontinue ()
6515 local
6516 Option<DAE.DAElist> odae;
6517 DAE.DAElist dae;
6518 Integer eqnSize,varSize,simpleEqnSize;
6519 String retStr,classNameStr;
6520 Flags.Flag flags;
6521
6522 // handle normal models
6523 case ()
6524 algorithm
6525 85 ExecStat.execStatReset();
6526 85 flags := loadCommandLineOptionsFromModel(className);
6527
6528 try
6529 85 (cache, _, odae) := runFrontEnd(cache, env, className, false);
6530
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 82 times.
85 SOME(dae) := odae;
6531 82 (varSize, eqnSize, simpleEqnSize) := CheckModel.checkModel(dae);
6532 82 FlagsUtil.saveFlags(flags);
6533 else
6534 3 FlagsUtil.saveFlags(flags);
6535 3 fail();
6536 end try;
6537
6538 82 classNameStr := AbsynUtil.pathString(className);
6539 164 retStr := stringAppendList({"Check of ",classNameStr," completed successfully.\nClass ",classNameStr," has ",String(eqnSize)," equation(s) and ",
6540 String(varSize)," variable(s).\n",String(simpleEqnSize)," of these are trivial equation(s)."});
6541 82 then Values.STRING(retStr);
6542
6543 case ()
6544 algorithm
6545
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 false := Interactive.existClass(className, SymbolTable.getAbsyn());
6546 ✗ Error.addMessage(Error.LOOKUP_ERROR, {AbsynUtil.pathString(className), "<TOP>"});
6547 then Values.STRING("");
6548
6549 // errors
6550 else
6551 algorithm
6552
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if Error.getNumMessages() == 0 then
6553 ✗ Error.addMessage(Error.INTERNAL_ERROR,
6554 {"Check of " + AbsynUtil.pathString(className) + " failed with no error message","<TOP>"});
6555 end if;
6556 then Values.STRING("");
6557
6558 end matchcontinue;
6559 end checkModel;
6560
6561 protected function getWithinStatement "To get a correct Within-path with unknown input-path."
6562 input Absyn.Path ip;
6563 output Absyn.Within op;
6564 algorithm op := matchcontinue ip
6565 local Absyn.Path path;
6566 ✗ case path algorithm path := AbsynUtil.stripLast(path); then Absyn.WITHIN(path);
6567 else Absyn.TOP();
6568 end matchcontinue;
6569 end getWithinStatement;
6570
6571 protected function dumpXMLDAE " author: fildo
6572 This function outputs the DAE system corresponding to a specific model."
6573 input FCore.Cache inCache;
6574 input FCore.Graph inEnv;
6575 input list<Values.Value> vals;
6576 input Absyn.Msg inMsg;
6577 output FCore.Cache outCache;
6578 output String xml_filename;
6579 algorithm
6580 (outCache,xml_filename) :=
6581 matchcontinue (inCache, inEnv, vals)
6582 local
6583 String cname_str,filenameprefix,compileDir,rewriteRulesFile,description;
6584 FCore.Graph env;
6585 Absyn.Path classname;
6586 BackendDAE.BackendDAE dlow,dlow_1,indexed_dlow;
6587 FCore.Cache cache;
6588 Boolean addOriginalAdjacencyMatrix,addSolvingInfo,addMathMLCode,dumpResiduals;
6589 DAE.DAElist dae;
6590
6591 case (cache, env, {Values.CODE(Absyn.C_TYPENAME(classname)),Values.STRING(string="flat"),
6592 Values.BOOL(addOriginalAdjacencyMatrix),Values.BOOL(addSolvingInfo),
6593 Values.BOOL(addMathMLCode),Values.BOOL(dumpResiduals),
6594 Values.STRING(filenameprefix),Values.STRING(rewriteRulesFile)})
6595 algorithm
6596 1 Error.clearMessages() "Clear messages";
6597
6598 // set the rewrite rules flag
6599 1 FlagsUtil.setConfigString(Flags.REWRITE_RULES_FILE, rewriteRulesFile);
6600 // load the rewrite rules
6601 1 RewriteRules.loadRules();
6602
6603
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
1 (cache, env, SOME(dae), _) := runFrontEnd(cache, env, classname, true, transform = true);
6604 1 description := DAEUtil.daeDescription(dae);
6605
6606 1 compileDir := System.pwd() + Autoconf.pathDelimiter;
6607 1 cname_str := AbsynUtil.pathString(classname);
6608
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
1 filenameprefix := if filenameprefix == "<default>" then cname_str else filenameprefix;
6609
6610 1 dlow := BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix,NONE())); //Verificare cosa fa
6611 1 dlow_1 := BackendDAEUtil.preOptimizeBackendDAE(dlow,NONE());
6612 1 dlow_1 := FindZeroCrossings.findZeroCrossings(dlow_1);
6613 1 xml_filename := stringAppendList({filenameprefix,".xml"});
6614
6615 // apply rewrite rules to the back-end
6616 1 dlow_1 := applyRewriteRulesOnBackend(dlow_1);
6617
6618 1 Print.clearBuf();
6619 1 XMLDump.dumpBackendDAE(dlow_1,addOriginalAdjacencyMatrix,addSolvingInfo,addMathMLCode,dumpResiduals,false);
6620 1 Print.writeBuf(xml_filename);
6621 1 Print.clearBuf();
6622
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 compileDir := if Testsuite.isRunning() then "" else compileDir;
6623
6624 // clear the rewrite rules!
6625 1 FlagsUtil.setConfigString(Flags.REWRITE_RULES_FILE, "");
6626 1 RewriteRules.clearRules();
6627 1 then
6628 (cache,stringAppendList({compileDir,xml_filename}));
6629
6630 case (cache, env, {Values.CODE(Absyn.C_TYPENAME(classname)),Values.STRING(string="optimiser"),
6631 Values.BOOL(addOriginalAdjacencyMatrix),Values.BOOL(addSolvingInfo),
6632 Values.BOOL(addMathMLCode),Values.BOOL(dumpResiduals),
6633 Values.STRING(filenameprefix),Values.STRING(rewriteRulesFile)})
6634 algorithm
6635 //asInSimulationCode==false => it's NOT necessary to do all the translation's steps before dumping with xml
6636 1 Error.clearMessages() "Clear messages";
6637
6638 // set the rewrite rules flag
6639 1 FlagsUtil.setConfigString(Flags.REWRITE_RULES_FILE, rewriteRulesFile);
6640 // load the rewrite rules
6641 1 RewriteRules.loadRules();
6642
6643
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
1 (cache, env, SOME(dae), _) := runFrontEnd(cache, env, classname, true, transform = true);
6644 1 description := DAEUtil.daeDescription(dae);
6645
6646 1 compileDir := System.pwd() + Autoconf.pathDelimiter;
6647 1 cname_str := AbsynUtil.pathString(classname);
6648
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
1 filenameprefix := if filenameprefix == "<default>" then cname_str else filenameprefix;
6649
6650 1 dlow := BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix,NONE())); //Verificare cosa fa
6651 1 dlow_1 := BackendDAEUtil.preOptimizeBackendDAE(dlow,NONE());
6652 1 dlow_1 := BackendDAEUtil.transformBackendDAE(dlow_1,NONE(),NONE(),NONE());
6653 1 dlow_1 := FindZeroCrossings.findZeroCrossings(dlow_1);
6654 1 xml_filename := stringAppendList({filenameprefix,".xml"});
6655
6656 // apply rewrite rules to the back-end
6657 1 dlow_1 := applyRewriteRulesOnBackend(dlow_1);
6658
6659 1 Print.clearBuf();
6660 1 XMLDump.dumpBackendDAE(dlow_1,addOriginalAdjacencyMatrix,addSolvingInfo,addMathMLCode,dumpResiduals,false);
6661 1 Print.writeBuf(xml_filename);
6662 1 Print.clearBuf();
6663
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 compileDir := if Testsuite.isRunning() then "" else compileDir;
6664
6665 // clear the rewrite rules!
6666 1 FlagsUtil.setConfigString(Flags.REWRITE_RULES_FILE, "");
6667 1 RewriteRules.clearRules();
6668 1 then
6669 (cache,stringAppendList({compileDir,xml_filename}));
6670
6671 case (cache, env, {Values.CODE(Absyn.C_TYPENAME(classname)),Values.STRING(string="backEnd"),
6672 Values.BOOL(addOriginalAdjacencyMatrix),Values.BOOL(addSolvingInfo),
6673 Values.BOOL(addMathMLCode),Values.BOOL(dumpResiduals),
6674 Values.STRING(filenameprefix),Values.STRING(rewriteRulesFile)})
6675 algorithm
6676 //asInSimulationCode==true => it's necessary to do all the translation's steps before dumping with xml
6677 ✗ Error.clearMessages() "Clear messages";
6678
6679 // set the rewrite rules flag
6680 ✗ FlagsUtil.setConfigString(Flags.REWRITE_RULES_FILE, rewriteRulesFile);
6681 // load the rewrite rules
6682 ✗ RewriteRules.loadRules();
6683
6684 ✗ (cache, env, SOME(dae), _) := runFrontEnd(cache, env, classname, true, transform = true);
6685 ✗ description := DAEUtil.daeDescription(dae);
6686
6687 ✗ compileDir := System.pwd() + Autoconf.pathDelimiter;
6688 ✗ cname_str := AbsynUtil.pathString(classname);
6689 ✗ filenameprefix := if filenameprefix == "<default>" then cname_str else filenameprefix;
6690
6691 ✗ dlow := BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix, NONE()));
6692 ✗ indexed_dlow := BackendDAEUtil.getSolvedSystem(dlow,"");
6693 ✗ xml_filename := stringAppendList({filenameprefix,".xml"});
6694
6695 // apply rewrite rules to the back-end
6696 ✗ indexed_dlow := applyRewriteRulesOnBackend(indexed_dlow);
6697
6698 ✗ Print.clearBuf();
6699 ✗ XMLDump.dumpBackendDAE(indexed_dlow,addOriginalAdjacencyMatrix,addSolvingInfo,addMathMLCode,dumpResiduals,false);
6700 ✗ Print.writeBuf(xml_filename);
6701 ✗ Print.clearBuf();
6702 ✗ compileDir := if Testsuite.isRunning() then "" else compileDir;
6703
6704 // clear the rewrite rules!
6705 ✗ FlagsUtil.setConfigString(Flags.REWRITE_RULES_FILE, "");
6706 ✗ RewriteRules.clearRules();
6707 ✗ then
6708 (cache,stringAppendList({compileDir,xml_filename}));
6709
6710 case (cache, env, {Values.CODE(Absyn.C_TYPENAME(classname)),Values.STRING(string="stateSpace"),
6711 Values.BOOL(addOriginalAdjacencyMatrix),Values.BOOL(addSolvingInfo),
6712 Values.BOOL(addMathMLCode),Values.BOOL(dumpResiduals),
6713 Values.STRING(filenameprefix),Values.STRING(rewriteRulesFile)})
6714 algorithm
6715 //asInSimulationCode==true => it's necessary to do all the translation's steps before dumping with xml
6716 ✗ Error.clearMessages() "Clear messages";
6717
6718 // set the rewrite rules flag
6719 ✗ FlagsUtil.setConfigString(Flags.REWRITE_RULES_FILE, rewriteRulesFile);
6720 // load the rewrite rules
6721 ✗ RewriteRules.loadRules();
6722
6723 ✗ (cache, env, SOME(dae), _) := runFrontEnd(cache, env, classname, true, transform = true);
6724 ✗ description := DAEUtil.daeDescription(dae);
6725
6726 ✗ compileDir := System.pwd() + Autoconf.pathDelimiter;
6727 ✗ cname_str := AbsynUtil.pathString(classname);
6728 ✗ filenameprefix := if filenameprefix == "<default>" then cname_str else filenameprefix;
6729
6730 ✗ dlow := BackendDAECreate.lower(dae,cache,env,BackendDAE.EXTRA_INFO(description,filenameprefix,NONE()));
6731 ✗ indexed_dlow := BackendDAEUtil.getSolvedSystem(dlow,"");
6732 ✗ xml_filename := stringAppendList({filenameprefix,".xml"});
6733
6734 // apply rewrite rules to the back-end
6735 ✗ indexed_dlow := applyRewriteRulesOnBackend(indexed_dlow);
6736
6737 ✗ Print.clearBuf();
6738 ✗ XMLDump.dumpBackendDAE(indexed_dlow,addOriginalAdjacencyMatrix,addSolvingInfo,addMathMLCode,dumpResiduals,true);
6739 ✗ Print.writeBuf(xml_filename);
6740 ✗ Print.clearBuf();
6741 ✗ compileDir := if Testsuite.isRunning() then "" else compileDir;
6742
6743 // clear the rewrite rules!
6744 ✗ FlagsUtil.setConfigString(Flags.REWRITE_RULES_FILE, "");
6745 ✗ RewriteRules.clearRules();
6746 ✗ then
6747 (cache,stringAppendList({compileDir,xml_filename}));
6748
6749 else
6750 algorithm
6751 // clear the rewrite rules if we fail!
6752 ✗ FlagsUtil.setConfigString(Flags.REWRITE_RULES_FILE, "");
6753 ✗ RewriteRules.clearRules();
6754 ✗ then fail();
6755
6756 end matchcontinue;
6757 end dumpXMLDAE;
6758
6759 protected function applyRewriteRulesOnBackend
6760 input BackendDAE.BackendDAE inBackendDAE;
6761 output BackendDAE.BackendDAE outBackendDAE;
6762 algorithm
6763
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 outBackendDAE := if RewriteRules.noRewriteRulesBackEnd() then inBackendDAE
6764 else BackendDAEOptimize.applyRewriteRulesBackend(inBackendDAE);
6765 end applyRewriteRulesOnBackend;
6766
6767 protected function getClassnamesInClassList
6768 input Absyn.Path inPath;
6769 input Absyn.Program inProgram;
6770 input Absyn.Class inClass;
6771 input Boolean inShowProtected;
6772 output list<String> outStrings;
6773 algorithm
6774 outStrings :=
6775 match (inClass, inShowProtected)
6776 local
6777 list<String> strlist;
6778 list<Absyn.ClassPart> parts;
6779 Boolean b;
6780 case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)), b)
6781 algorithm
6782 ✗ strlist := ProgramUtil.getClassnamesInParts(parts,b,false);
6783 then
6784 strlist;
6785
6786 case (Absyn.CLASS(body = Absyn.DERIVED(typeSpec=Absyn.TPATH())), _)
6787 algorithm
6788 then
6789 {};
6790
6791 case (Absyn.CLASS(body = Absyn.OVERLOAD(_, _)), _)
6792 algorithm
6793 then {};
6794
6795 case (Absyn.CLASS(body = Absyn.ENUMERATION(_, _)), _)
6796 algorithm
6797 then {};
6798
6799 case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts=parts)), b)
6800 algorithm
6801 ✗ strlist := ProgramUtil.getClassnamesInParts(parts,b,false);
6802 then strlist;
6803
6804 case (Absyn.CLASS(body = Absyn.PDER(_,_,_)), _)
6805 algorithm
6806 then {};
6807
6808 end match;
6809 end getClassnamesInClassList;
6810
6811 protected function joinPaths
6812 input String child;
6813 input Absyn.Path parent;
6814 output Absyn.Path outPath;
6815 algorithm
6816 outPath := match (child, parent)
6817 local
6818 Absyn.Path r, res;
6819 String c;
6820 case (c, r)
6821 algorithm
6822 ✗ res := AbsynUtil.joinPaths(r, Absyn.IDENT(c));
6823 then res;
6824 end match;
6825 end joinPaths;
6826
6827 protected function getAllClassPathsRecursive
6828 "@author adrpo
6829 Returns all paths of the classes recursively defined in a given class with the specified path."
6830 input Absyn.Path inPath "the given class path";
6831 input Boolean inCheckProtected;
6832 input Absyn.Program inProgram "the program";
6833 output list<Absyn.Path> outPaths;
6834 algorithm
6835 outPaths :=
6836 matchcontinue (inCheckProtected, inProgram)
6837 local
6838 Absyn.Class cdef;
6839 String parent_string, s;
6840 list<String> strlst;
6841 Absyn.Program p;
6842 list<Absyn.Path> result_path_lst, result;
6843 Boolean b;
6844 case (b, p)
6845 algorithm
6846 ✗ cdef := ProgramUtil.getPathedClassInProgram(inPath, p);
6847 ✗ strlst := getClassnamesInClassList(inPath, p, cdef, b);
6848 ✗ result_path_lst := List.map1(strlst, joinPaths, inPath);
6849 ✗ result := List.flatten(List.map2(result_path_lst, getAllClassPathsRecursive, b, p));
6850 then
6851 inPath::result;
6852 else
6853 algorithm
6854 ✗ parent_string := AbsynUtil.pathString(inPath);
6855 ✗ s := Error.printMessagesStr(false);
6856 ✗ s := stringAppendList({parent_string,"->","PROBLEM GETTING CLASS PATHS: ", s, "\n"});
6857 ✗ print(s);
6858 then {};
6859 end matchcontinue;
6860 end getAllClassPathsRecursive;
6861
6862 public function checkAllModelsRecursive
6863 "@author adrpo
6864 checks all models and returns number of variables and equations"
6865 input FCore.Cache inCache;
6866 input FCore.Graph inEnv;
6867 input Absyn.Path className;
6868 input Boolean inCheckProtected;
6869 input Absyn.Msg inMsg;
6870 output FCore.Cache outCache;
6871 output Values.Value outValue;
6872 algorithm
6873 (outCache,outValue):=
6874 matchcontinue (inCache, inEnv, inCheckProtected, inMsg)
6875 local
6876 list<Absyn.Path> allClassPaths;
6877 Absyn.Msg msg;
6878 FCore.Cache cache;
6879 String ret;
6880 FCore.Graph env;
6881 Boolean b;
6882 Integer failed;
6883
6884 case (cache, env, b, msg)
6885 algorithm
6886 ✗ allClassPaths := getAllClassPathsRecursive(className, b, SymbolTable.getAbsyn());
6887 ✗ print("Number of classes to check: " + intString(listLength(allClassPaths)) + "\n");
6888 // print ("All paths:\n" + stringDelimitList(List.map(allClassPaths, AbsynUtil.pathString), "\n") + "\n");
6889 ✗ failed := checkAll(cache, env, allClassPaths, msg, not Testsuite.isRunning(), 0);
6890 ✗ ret := "Number of classes checked / failed: " + intString(listLength(allClassPaths)) + "/" + intString(failed);
6891 ✗ then
6892 (cache,Values.STRING(ret));
6893
6894 case (cache, _, _, _)
6895 algorithm
6896 ✗ ret := stringAppend("Error checking: ", AbsynUtil.pathString(className));
6897 ✗ then
6898 (cache,Values.STRING(ret));
6899 end matchcontinue;
6900 end checkAllModelsRecursive;
6901
6902 function failOrSuccess
6903 "@author adrpo"
6904 input String inStr;
6905 output String outStr;
6906 output Boolean failed = false;
6907 algorithm
6908 outStr := matchcontinue inStr
6909 local Integer res;
6910 case _
6911 algorithm
6912 ✗ res := System.stringFind(inStr, "successfully");
6913 ✗ true := (res >= 0);
6914 failed := false;
6915 then
6916 "OK";
6917 else
6918 algorithm
6919 failed := true;
6920 then
6921 "FAILED!";
6922 end matchcontinue;
6923 end failOrSuccess;
6924
6925 function checkAll
6926 "@author adrpo
6927 checks all models and returns number of variables and equations"
6928 input FCore.Cache inCache;
6929 input FCore.Graph inEnv;
6930 input list<Absyn.Path> allClasses;
6931 input Absyn.Msg inMsg;
6932 input Boolean reportTimes;
6933 input output Integer failed;
6934 protected
6935 Absyn.Program p;
6936 list<Absyn.Path> rest;
6937 Absyn.Path className;
6938 String str, s, smsg;
6939 Real t1, t2, elapsedTime;
6940 Absyn.Class c;
6941 Boolean f = false;
6942 algorithm
6943 ✗ p := SymbolTable.getAbsyn();
6944 () := matchcontinue allClasses
6945 case {} then ();
6946
6947 case className::rest
6948 algorithm
6949 ✗ c := ProgramUtil.getPathedClassInProgram(className, p);
6950 // filter out partial classes
6951 // Absyn.CLASS(partialPrefix = false) = c; // do not filter partial classes
6952 // filter out packages
6953 ✗ false := Interactive.isPackage(className, p);
6954 // filter out functions
6955 // false = Interactive.isFunction(cr, p);
6956 // filter out types
6957 ✗ false := Interactive.isType(className, p);
6958 ✗ print("Checking: " + Dump.unparseClassAttributesStr(c) + " " + AbsynUtil.pathString(className) + "... ");
6959 ✗ t1 := clock();
6960 ✗ FlagsUtil.setConfigBool(Flags.CHECK_MODEL, true);
6961 ✗ (_,Values.STRING(str)) := checkModel(FCore.emptyCache(), inEnv, className, inMsg);
6962 ✗ FlagsUtil.setConfigBool(Flags.CHECK_MODEL, false);
6963 ✗ t2 := clock();
6964 ✗ elapsedTime := t2 - t1;
6965 ✗ s := realString(elapsedTime);
6966 ✗ (smsg, f) := failOrSuccess(str);
6967 ✗ failed := if f then failed + 1 else failed;
6968
6969 ✗ if reportTimes then
6970 ✗ print (s + " seconds -> " + smsg + "\n");
6971 else
6972 ✗ print(smsg + "\n");
6973 end if;
6974
6975 ✗ if not stringEmpty(str) then
6976 ✗ print("\t");
6977 end if;
6978
6979 ✗ print (System.stringReplace(str, "\n", "\n\t"));
6980 ✗ print ("\n");
6981 ✗ print ("Error String:\n" + Print.getErrorString() + "\n");
6982 ✗ print ("Error Buffer:\n" + ErrorExt.printMessagesStr(false) + "\n");
6983 ✗ print ("#" + (if f then "[-]" else "[+]") + ", " +
6984 (if reportTimes then realString(elapsedTime) + ", " else "") +
6985 AbsynUtil.pathString(className) + "\n");
6986 ✗ print ("-------------------------------------------------------------------------\n");
6987 ✗ failed := checkAll(inCache, inEnv, rest, inMsg, reportTimes, failed);
6988 then ();
6989
6990 case className::rest
6991 algorithm
6992 ✗ c := ProgramUtil.getPathedClassInProgram(className, p);
6993 ✗ print("Checking skipped: " + Dump.unparseClassAttributesStr(c) + " " + AbsynUtil.pathString(className) + "...\n");
6994 ✗ failed := checkAll(inCache, inEnv, rest, inMsg, reportTimes, failed);
6995 then
6996 ();
6997 end matchcontinue;
6998 end checkAll;
6999
7000 protected function getAlgorithms
7001 "Counts the number of Algorithm sections in a class."
7002 input Absyn.Class inClass;
7003 output list<Absyn.ClassPart> outList;
7004 algorithm
7005 outList := match inClass
7006 local
7007 list<Absyn.ClassPart> algsList;
7008 list<Absyn.ClassPart> parts;
7009 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
7010 algorithm
7011 ✗ algsList := getAlgorithmsInClassParts(parts);
7012 then
7013 algsList;
7014 // check also the case model extends X end X;
7015 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
7016 algorithm
7017 ✗ algsList := getAlgorithmsInClassParts(parts);
7018 then
7019 algsList;
7020 case Absyn.CLASS(body = Absyn.DERIVED()) then {};
7021 end match;
7022 end getAlgorithms;
7023
7024 protected function getAlgorithmsInClassParts
7025 "Helper function to getAlgorithms"
7026 input list<Absyn.ClassPart> inAbsynClassPartLst;
7027 output list<Absyn.ClassPart> outList;
7028 algorithm
7029 outList := match inAbsynClassPartLst
7030 local
7031 list<Absyn.ClassPart> algsList;
7032 list<Absyn.ClassPart> xs;
7033 Absyn.ClassPart cp;
7034 case (cp as Absyn.ALGORITHMS()) :: xs
7035 algorithm
7036 ✗ algsList := getAlgorithmsInClassParts(xs);
7037 then
7038 cp::algsList;
7039 case _ :: xs
7040 algorithm
7041 ✗ algsList := getAlgorithmsInClassParts(xs);
7042 then
7043 algsList;
7044 case {} then {};
7045 end match;
7046 end getAlgorithmsInClassParts;
7047
7048 protected function getNthAlgorithm
7049 "Returns the Nth Algorithm section from a class."
7050 input Absyn.Class inClass;
7051 input Integer inInteger;
7052 output String outString;
7053 protected list<Absyn.ClassPart> algsList;
7054 algorithm
7055 ✗ algsList := getAlgorithms(inClass);
7056 ✗ outString := getNthAlgorithmInClass(listGet(algsList, inInteger));
7057 end getNthAlgorithm;
7058
7059 protected function getNthAlgorithmInClass
7060 "Helper function to getNthAlgorithm."
7061 input Absyn.ClassPart inClassPart;
7062 output String outString;
7063 algorithm
7064 outString := match inClassPart
7065 local
7066 String str;
7067 list<Absyn.AlgorithmItem> algs;
7068 case Absyn.ALGORITHMS(contents = algs)
7069 algorithm
7070 ✗ str := Dump.unparseAlgorithmStrLst(algs, "\n");
7071 then
7072 str;
7073 end match;
7074 end getNthAlgorithmInClass;
7075
7076 protected function getInitialAlgorithms
7077 "Counts the number of Initial Algorithm sections in a class."
7078 input Absyn.Class inClass;
7079 output list<Absyn.ClassPart> outList;
7080 algorithm
7081 outList := match inClass
7082 local
7083 list<Absyn.ClassPart> algsList;
7084 list<Absyn.ClassPart> parts;
7085 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
7086 algorithm
7087 ✗ algsList := getInitialAlgorithmsInClassParts(parts);
7088 then
7089 algsList;
7090 // check also the case model extends X end X;
7091 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
7092 algorithm
7093 ✗ algsList := getInitialAlgorithmsInClassParts(parts);
7094 then
7095 algsList;
7096 case Absyn.CLASS(body = Absyn.DERIVED()) then {};
7097 end match;
7098 end getInitialAlgorithms;
7099
7100 protected function getInitialAlgorithmsInClassParts
7101 "Helper function to getInitialAlgorithms"
7102 input list<Absyn.ClassPart> inAbsynClassPartLst;
7103 output list<Absyn.ClassPart> outList;
7104 algorithm
7105 outList := match inAbsynClassPartLst
7106 local
7107 list<Absyn.ClassPart> algsList;
7108 list<Absyn.ClassPart> xs;
7109 Absyn.ClassPart cp;
7110 case (cp as Absyn.INITIALALGORITHMS()) :: xs
7111 algorithm
7112 ✗ algsList := getInitialAlgorithmsInClassParts(xs);
7113 then
7114 cp::algsList;
7115 case _ :: xs
7116 algorithm
7117 ✗ algsList := getInitialAlgorithmsInClassParts(xs);
7118 then
7119 algsList;
7120 case {} then {};
7121 end match;
7122 end getInitialAlgorithmsInClassParts;
7123
7124 protected function getNthInitialAlgorithm
7125 "Returns the Nth Initial Algorithm section from a class."
7126 input Absyn.Class inClass;
7127 input Integer inInteger;
7128 output String outString;
7129 protected list<Absyn.ClassPart> algsList;
7130 algorithm
7131 ✗ algsList := getInitialAlgorithms(inClass);
7132 ✗ outString := getNthInitialAlgorithmInClass(listGet(algsList, inInteger));
7133 end getNthInitialAlgorithm;
7134
7135 protected function getNthInitialAlgorithmInClass
7136 "Helper function to getNthInitialAlgorithm."
7137 input Absyn.ClassPart inClassPart;
7138 output String outString;
7139 algorithm
7140 outString := match inClassPart
7141 local
7142 String str;
7143 list<Absyn.AlgorithmItem> algs;
7144 case Absyn.INITIALALGORITHMS(contents = algs)
7145 algorithm
7146 ✗ str := Dump.unparseAlgorithmStrLst(algs, "\n");
7147 then
7148 str;
7149 end match;
7150 end getNthInitialAlgorithmInClass;
7151
7152 protected function getAlgorithmItemsCount
7153 "Counts the number of Algorithm items in a class."
7154 input Absyn.Class inClass;
7155 output Integer outInteger;
7156 algorithm
7157 outInteger := match inClass
7158 local
7159 list<Absyn.ClassPart> parts;
7160 Integer count;
7161 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
7162 algorithm
7163 ✗ count := getAlgorithmItemsCountInClassParts(parts);
7164 then
7165 count;
7166 // check also the case model extends X end X;
7167 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
7168 algorithm
7169 ✗ count := getAlgorithmItemsCountInClassParts(parts);
7170 then
7171 count;
7172 case Absyn.CLASS(body = Absyn.DERIVED()) then 0;
7173 end match;
7174 end getAlgorithmItemsCount;
7175
7176 protected function getAlgorithmItemsCountInClassParts
7177 "Helper function to getAlgorithmItemsCount"
7178 input list<Absyn.ClassPart> inAbsynClassPartLst;
7179 output Integer outInteger;
7180 algorithm
7181 outInteger := match inAbsynClassPartLst
7182 local
7183 list<Absyn.AlgorithmItem> algs;
7184 list<Absyn.ClassPart> xs;
7185 Integer c1, c2, res;
7186 case Absyn.ALGORITHMS(contents = algs) :: xs
7187 algorithm
7188 ✗ c1 := getAlgorithmItemsCountInAlgorithmItems(algs);
7189 c2 := getAlgorithmItemsCountInClassParts(xs);
7190 then
7191 c1 + c2;
7192 case _ :: xs
7193 algorithm
7194 ✗ res := getAlgorithmItemsCountInClassParts(xs);
7195 then
7196 res;
7197 case {} then 0;
7198 end match;
7199 end getAlgorithmItemsCountInClassParts;
7200
7201 protected function getAlgorithmItemsCountInAlgorithmItems
7202 "Helper function to getAlgorithmItemsCountInClassParts"
7203 input list<Absyn.AlgorithmItem> inAbsynAlgorithmItemLst;
7204 output Integer outInteger;
7205 algorithm
7206 outInteger := match inAbsynAlgorithmItemLst
7207 local
7208 list<Absyn.AlgorithmItem> xs;
7209 Integer c1, res;
7210 case Absyn.ALGORITHMITEM() :: xs
7211 algorithm
7212 c1 := getAlgorithmItemsCountInAlgorithmItems(xs);
7213 then
7214 c1 + 1;
7215 case _ :: xs
7216 algorithm
7217 ✗ res := getAlgorithmItemsCountInAlgorithmItems(xs);
7218 then
7219 res;
7220 case {} then 0;
7221 end match;
7222 end getAlgorithmItemsCountInAlgorithmItems;
7223
7224 protected function getNthAlgorithmItem
7225 "Returns the Nth Algorithm Item from a class."
7226 input Absyn.Class inClass;
7227 input Integer inInteger;
7228 output String outString;
7229 protected
7230 list<Absyn.ClassPart> parts;
7231 algorithm
7232 outString := match inClass
7233 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
7234 ✗ then getNthAlgorithmItemInClassParts(parts,inInteger);
7235 // check also the case model extends X end X;
7236 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
7237 ✗ then getNthAlgorithmItemInClassParts(parts,inInteger);
7238 end match;
7239 end getNthAlgorithmItem;
7240
7241 protected function getNthAlgorithmItemInClassParts
7242 "Helper function to getNthAlgorithmItem"
7243 input list<Absyn.ClassPart> inAbsynClassPartLst;
7244 input Integer inInteger;
7245 output String outString;
7246 algorithm
7247 outString := matchcontinue (inAbsynClassPartLst,inInteger)
7248 local
7249 String str;
7250 list<Absyn.AlgorithmItem> algs;
7251 list<Absyn.ClassPart> xs;
7252 Integer n,c1,newn;
7253 case ((Absyn.ALGORITHMS(contents = algs) :: _),n)
7254 algorithm
7255 ✗ str := getNthAlgorithmItemInAlgorithms(algs, n);
7256 then
7257 str;
7258 case ((Absyn.ALGORITHMS(contents = algs) :: xs),n) /* The rule above failed, subtract the number of algorithms in the first section and try with the rest of the classparts */
7259 algorithm
7260 ✗ c1 := getAlgorithmItemsCountInAlgorithmItems(algs);
7261 ✗ newn := n - c1;
7262 ✗ str := getNthAlgorithmItemInClassParts(xs, newn);
7263 then
7264 str;
7265 case ((_ :: xs),n)
7266 algorithm
7267 ✗ str := getNthAlgorithmItemInClassParts(xs, n);
7268 then
7269 str;
7270 end matchcontinue;
7271 end getNthAlgorithmItemInClassParts;
7272
7273 protected function getNthAlgorithmItemInAlgorithms
7274 " This function takes an Algorithm list and an int
7275 and returns the nth algorithm item as String.
7276 If the number is larger than the number of algorithms
7277 in the list, the function fails. Helper function to getNthAlgorithmItemInClassParts."
7278 input list<Absyn.AlgorithmItem> inAbsynAlgorithmItemLst;
7279 input Integer inInteger;
7280 output String outString;
7281 algorithm
7282 outString := matchcontinue (inAbsynAlgorithmItemLst,inInteger)
7283 local
7284 String str;
7285 Absyn.Algorithm alg;
7286 Option<Absyn.Comment> cmt;
7287 SourceInfo inf;
7288 list<Absyn.AlgorithmItem> xs;
7289 Integer newn,n;
7290 case ((Absyn.ALGORITHMITEM(algorithm_ = alg, comment = cmt, info = inf) :: _), 1)
7291 algorithm
7292 ✗ str := Dump.unparseAlgorithmStr(Absyn.ALGORITHMITEM(alg, cmt, inf));
7293 then
7294 str;
7295 case ((_ :: xs),n)
7296 algorithm
7297 ✗ newn := n - 1;
7298 ✗ str := getNthAlgorithmItemInAlgorithms(xs, newn);
7299 then
7300 str;
7301 case ({},_) then fail();
7302 end matchcontinue;
7303 end getNthAlgorithmItemInAlgorithms;
7304
7305 protected function getInitialAlgorithmItemsCount
7306 "Counts the number of Initial Algorithm items in a class."
7307 input Absyn.Class inClass;
7308 output Integer outInteger;
7309 algorithm
7310 outInteger := match inClass
7311 local
7312 list<Absyn.ClassPart> parts;
7313 Integer count;
7314 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
7315 algorithm
7316 ✗ count := getInitialAlgorithmItemsCountInClassParts(parts);
7317 then
7318 count;
7319 // check also the case model extends X end X;
7320 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
7321 algorithm
7322 ✗ count := getInitialAlgorithmItemsCountInClassParts(parts);
7323 then
7324 count;
7325 case Absyn.CLASS(body = Absyn.DERIVED()) then 0;
7326 end match;
7327 end getInitialAlgorithmItemsCount;
7328
7329 protected function getInitialAlgorithmItemsCountInClassParts
7330 "Helper function to getInitialAlgorithmItemsCount"
7331 input list<Absyn.ClassPart> inAbsynClassPartLst;
7332 output Integer outInteger;
7333 algorithm
7334 outInteger := match inAbsynClassPartLst
7335 local
7336 list<Absyn.AlgorithmItem> algs;
7337 list<Absyn.ClassPart> xs;
7338 Integer c1, c2, res;
7339 case Absyn.INITIALALGORITHMS(contents = algs) :: xs
7340 algorithm
7341 ✗ c1 := getAlgorithmItemsCountInAlgorithmItems(algs);
7342 c2 := getInitialAlgorithmItemsCountInClassParts(xs);
7343 then
7344 c1 + c2;
7345 case _ :: xs
7346 algorithm
7347 ✗ res := getInitialAlgorithmItemsCountInClassParts(xs);
7348 then
7349 res;
7350 case {} then 0;
7351 end match;
7352 end getInitialAlgorithmItemsCountInClassParts;
7353
7354 protected function getNthInitialAlgorithmItem
7355 "Returns the Nth Initial Algorithm Item from a class."
7356 input Absyn.Class inClass;
7357 input Integer inInteger;
7358 output String outString;
7359 algorithm
7360 outString := match (inClass,inInteger)
7361 local
7362 list<Absyn.ClassPart> parts;
7363 String str;
7364 Integer n;
7365 case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),n)
7366 algorithm
7367 ✗ str := getNthInitialAlgorithmItemInClassParts(parts,n);
7368 then
7369 str;
7370 // check also the case model extends X end X;
7371 case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)),n)
7372 algorithm
7373 ✗ str := getNthInitialAlgorithmItemInClassParts(parts,n);
7374 then
7375 str;
7376 end match;
7377 end getNthInitialAlgorithmItem;
7378
7379 protected function getNthInitialAlgorithmItemInClassParts
7380 "Helper function to getNthInitialAlgorithmItem"
7381 input list<Absyn.ClassPart> inAbsynClassPartLst;
7382 input Integer inInteger;
7383 output String outString;
7384 algorithm
7385 outString := matchcontinue (inAbsynClassPartLst,inInteger)
7386 local
7387 String str;
7388 list<Absyn.AlgorithmItem> algs;
7389 list<Absyn.ClassPart> xs;
7390 Integer n,c1,newn;
7391 case ((Absyn.INITIALALGORITHMS(contents = algs) :: _),n)
7392 algorithm
7393 ✗ str := getNthAlgorithmItemInAlgorithms(algs, n);
7394 then
7395 str;
7396 case ((Absyn.INITIALALGORITHMS(contents = algs) :: xs),n) /* The rule above failed, subtract the number of algorithms in the first section and try with the rest of the classparts */
7397 algorithm
7398 ✗ c1 := getAlgorithmItemsCountInAlgorithmItems(algs);
7399 ✗ newn := n - c1;
7400 ✗ str := getNthInitialAlgorithmItemInClassParts(xs, newn);
7401 then
7402 str;
7403 case ((_ :: xs),n)
7404 algorithm
7405 ✗ str := getNthInitialAlgorithmItemInClassParts(xs, n);
7406 then
7407 str;
7408 end matchcontinue;
7409 end getNthInitialAlgorithmItemInClassParts;
7410
7411 protected function getEquations
7412 "Counts the number of Equation sections in a class."
7413 input Absyn.Class inClass;
7414 output list<Absyn.ClassPart> outList;
7415 algorithm
7416 outList := match inClass
7417 local
7418 list<Absyn.ClassPart> eqsList;
7419 list<Absyn.ClassPart> parts;
7420 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
7421 algorithm
7422 ✗ eqsList := getEquationsInClassParts(parts);
7423 then
7424 eqsList;
7425 // check also the case model extends X end X;
7426 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
7427 algorithm
7428 ✗ eqsList := getEquationsInClassParts(parts);
7429 then
7430 eqsList;
7431 case Absyn.CLASS(body = Absyn.DERIVED()) then {};
7432 end match;
7433 end getEquations;
7434
7435 protected function getEquationsInClassParts
7436 "Helper function to getEquations"
7437 input list<Absyn.ClassPart> inAbsynClassPartLst;
7438 output list<Absyn.ClassPart> outList;
7439 algorithm
7440 outList := match inAbsynClassPartLst
7441 local
7442 list<Absyn.ClassPart> eqsList;
7443 list<Absyn.ClassPart> xs;
7444 Absyn.ClassPart cp;
7445 case (cp as Absyn.EQUATIONS()) :: xs
7446 algorithm
7447 ✗ eqsList := getEquationsInClassParts(xs);
7448 then
7449 cp::eqsList;
7450 case _ :: xs
7451 algorithm
7452 ✗ eqsList := getEquationsInClassParts(xs);
7453 then
7454 eqsList;
7455 case {} then {};
7456 end match;
7457 end getEquationsInClassParts;
7458
7459 protected function getNthEquation
7460 "Returns the Nth Equation section from a class."
7461 input Absyn.Class inClass;
7462 input Integer inInteger;
7463 output String outString;
7464 protected list<Absyn.ClassPart> eqsList;
7465 algorithm
7466 ✗ eqsList := getEquations(inClass);
7467 ✗ outString := getNthEquationInClass(listGet(eqsList, inInteger));
7468 end getNthEquation;
7469
7470 protected function getNthEquationInClass
7471 "Helper function to getNthEquation"
7472 input Absyn.ClassPart inClassPart;
7473 output String outString;
7474 algorithm
7475 outString := match inClassPart
7476 local
7477 String str;
7478 list<Absyn.EquationItem> eqs;
7479 case Absyn.EQUATIONS(contents = eqs)
7480 algorithm
7481 ✗ str := Dump.unparseEquationItemStrLst(eqs, "\n");
7482 then
7483 str;
7484 end match;
7485 end getNthEquationInClass;
7486
7487 protected function getInitialEquations
7488 "Counts the number of Initial Equation sections in a class."
7489 input Absyn.Class inClass;
7490 output list<Absyn.ClassPart> outList;
7491 algorithm
7492 outList := match inClass
7493 local
7494 list<Absyn.ClassPart> eqsList;
7495 list<Absyn.ClassPart> parts;
7496 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
7497 algorithm
7498 ✗ eqsList := getInitialEquationsInClassParts(parts);
7499 then
7500 eqsList;
7501 // check also the case model extends X end X;
7502 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
7503 algorithm
7504 ✗ eqsList := getInitialEquationsInClassParts(parts);
7505 then
7506 eqsList;
7507 case Absyn.CLASS(body = Absyn.DERIVED()) then {};
7508 end match;
7509 end getInitialEquations;
7510
7511 protected function getInitialEquationsInClassParts
7512 "Helper function to getInitialEquations"
7513 input list<Absyn.ClassPart> inAbsynClassPartLst;
7514 output list<Absyn.ClassPart> outList;
7515 algorithm
7516 outList := match inAbsynClassPartLst
7517 local
7518 list<Absyn.ClassPart> eqsList;
7519 list<Absyn.ClassPart> xs;
7520 Absyn.ClassPart cp;
7521 case (cp as Absyn.INITIALEQUATIONS()) :: xs
7522 algorithm
7523 ✗ eqsList := getInitialEquationsInClassParts(xs);
7524 then
7525 cp::eqsList;
7526 case _ :: xs
7527 algorithm
7528 ✗ eqsList := getInitialEquationsInClassParts(xs);
7529 then
7530 eqsList;
7531 case {} then {};
7532 end match;
7533 end getInitialEquationsInClassParts;
7534
7535 protected function getNthInitialEquation
7536 "Returns the Nth Initial Equation section from a class."
7537 input Absyn.Class inClass;
7538 input Integer inInteger;
7539 output String outString;
7540 protected list<Absyn.ClassPart> eqsList;
7541 algorithm
7542 ✗ eqsList := getInitialEquations(inClass);
7543 ✗ outString := getNthInitialEquationInClass(listGet(eqsList, inInteger));
7544 end getNthInitialEquation;
7545
7546 protected function getNthInitialEquationInClass
7547 "Helper function to getNthInitialEquation."
7548 input Absyn.ClassPart inClassPart;
7549 output String outString;
7550 algorithm
7551 outString := match inClassPart
7552 local
7553 String str;
7554 list<Absyn.EquationItem> eqs;
7555 case Absyn.INITIALEQUATIONS(contents = eqs)
7556 algorithm
7557 ✗ str := Dump.unparseEquationItemStrLst(eqs, "\n");
7558 then
7559 str;
7560 end match;
7561 end getNthInitialEquationInClass;
7562
7563 protected function getEquationItemsCount
7564 "Counts the number of Equation items in a class."
7565 input Absyn.Class inClass;
7566 output Integer outInteger;
7567 algorithm
7568 outInteger := match inClass
7569 local
7570 list<Absyn.ClassPart> parts;
7571 Integer count;
7572 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
7573 algorithm
7574 ✗ count := getEquationItemsCountInClassParts(parts);
7575 then
7576 count;
7577 // check also the case model extends X end X;
7578 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
7579 algorithm
7580 ✗ count := getEquationItemsCountInClassParts(parts);
7581 then
7582 count;
7583 case Absyn.CLASS(body = Absyn.DERIVED()) then 0;
7584 end match;
7585 end getEquationItemsCount;
7586
7587 protected function getEquationItemsCountInClassParts
7588 "Helper function to getEquationItemsCount"
7589 input list<Absyn.ClassPart> inAbsynClassPartLst;
7590 output Integer outInteger;
7591 algorithm
7592 outInteger := match inAbsynClassPartLst
7593 local
7594 list<Absyn.EquationItem> eqs;
7595 list<Absyn.ClassPart> xs;
7596 Integer c1, c2, res;
7597 case Absyn.EQUATIONS(contents = eqs) :: xs
7598 algorithm
7599 ✗ c1 := getEquationItemsCountInEquationItems(eqs);
7600 c2 := getEquationItemsCountInClassParts(xs);
7601 then
7602 c1 + c2;
7603 case _ :: xs
7604 algorithm
7605 ✗ res := getEquationItemsCountInClassParts(xs);
7606 then
7607 res;
7608 case {} then 0;
7609 end match;
7610 end getEquationItemsCountInClassParts;
7611
7612 protected function getEquationItemsCountInEquationItems
7613 "Helper function to getEquationItemsCountInClassParts"
7614 input list<Absyn.EquationItem> inAbsynEquationItemLst;
7615 output Integer outInteger;
7616 algorithm
7617 outInteger := match inAbsynEquationItemLst
7618 local
7619 list<Absyn.EquationItem> xs;
7620 Integer c1, res;
7621 case Absyn.EQUATIONITEM() :: xs
7622 algorithm
7623 c1 := getEquationItemsCountInEquationItems(xs);
7624 then
7625 c1 + 1;
7626 case _ :: xs
7627 algorithm
7628 ✗ res := getEquationItemsCountInEquationItems(xs);
7629 then
7630 res;
7631 case {} then 0;
7632 end match;
7633 end getEquationItemsCountInEquationItems;
7634
7635 protected function getNthEquationItem
7636 "Returns the Nth Equation Item from a class."
7637 input Absyn.Class inClass;
7638 input Integer inInteger;
7639 output String outString;
7640 algorithm
7641 outString := match (inClass,inInteger)
7642 local
7643 list<Absyn.ClassPart> parts;
7644 String str;
7645 Integer n;
7646 case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),n)
7647 algorithm
7648 ✗ str := getNthEquationItemInClassParts(parts,n);
7649 then
7650 str;
7651 // check also the case model extends X end X;
7652 case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)),n)
7653 algorithm
7654 ✗ str := getNthEquationItemInClassParts(parts,n);
7655 then
7656 str;
7657 end match;
7658 end getNthEquationItem;
7659
7660 protected function getNthEquationItemInClassParts
7661 "Helper function to getNthEquationItem"
7662 input list<Absyn.ClassPart> inAbsynClassPartLst;
7663 input Integer inInteger;
7664 output String outString;
7665 algorithm
7666 outString := matchcontinue (inAbsynClassPartLst,inInteger)
7667 local
7668 String str;
7669 list<Absyn.EquationItem> eqs;
7670 list<Absyn.ClassPart> xs;
7671 Integer n,c1,newn;
7672 case ((Absyn.EQUATIONS(contents = eqs) :: _),n)
7673 algorithm
7674 ✗ str := getNthEquationItemInEquations(eqs, n);
7675 then
7676 str;
7677 case ((Absyn.EQUATIONS(contents = eqs) :: xs),n) /* The rule above failed, subtract the number of equations in the first section and try with the rest of the classparts */
7678 algorithm
7679 ✗ c1 := getEquationItemsCountInEquationItems(eqs);
7680 ✗ newn := n - c1;
7681 ✗ str := getNthEquationItemInClassParts(xs, newn);
7682 then
7683 str;
7684 case ((_ :: xs),n)
7685 algorithm
7686 ✗ str := getNthEquationItemInClassParts(xs, n);
7687 then
7688 str;
7689 end matchcontinue;
7690 end getNthEquationItemInClassParts;
7691
7692 protected function getNthEquationItemInEquations
7693 " This function takes an Equation list and an int
7694 and returns the nth Equation item as String.
7695 If the number is larger than the number of algorithms
7696 in the list, the function fails. Helper function to getNthEquationItemInClassParts."
7697 input list<Absyn.EquationItem> inAbsynEquationItemLst;
7698 input Integer inInteger;
7699 output String outString;
7700 algorithm
7701 outString := matchcontinue (inAbsynEquationItemLst,inInteger)
7702 local
7703 String str;
7704 Absyn.Equation eq;
7705 list<Absyn.EquationItem> xs;
7706 Integer newn,n;
7707 case ((Absyn.EQUATIONITEM(equation_ = eq) :: _), 1)
7708 algorithm
7709 ✗ str := Dump.unparseEquationStr(eq);
7710 ✗ str := stringAppend(str, ";");
7711 ✗ str := System.trim(str, " ");
7712 then
7713 str;
7714 case ((_ :: xs),n)
7715 algorithm
7716 ✗ newn := n - 1;
7717 ✗ str := getNthEquationItemInEquations(xs, newn);
7718 then
7719 str;
7720 case ({},_) then fail();
7721 end matchcontinue;
7722 end getNthEquationItemInEquations;
7723
7724 protected function getInitialEquationItemsCount
7725 "Counts the number of Initial Equation items in a class."
7726 input Absyn.Class inClass;
7727 output Integer outInteger;
7728 algorithm
7729 outInteger := match inClass
7730 local
7731 list<Absyn.ClassPart> parts;
7732 Integer count;
7733 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
7734 algorithm
7735 ✗ count := getInitialEquationItemsCountInClassParts(parts);
7736 then
7737 count;
7738 // check also the case model extends X end X;
7739 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
7740 algorithm
7741 ✗ count := getInitialEquationItemsCountInClassParts(parts);
7742 then
7743 count;
7744 case Absyn.CLASS(body = Absyn.DERIVED()) then 0;
7745 end match;
7746 end getInitialEquationItemsCount;
7747
7748 protected function getInitialEquationItemsCountInClassParts
7749 "Helper function to getInitialEquationItemsCount"
7750 input list<Absyn.ClassPart> inAbsynClassPartLst;
7751 output Integer outInteger;
7752 algorithm
7753 outInteger := match inAbsynClassPartLst
7754 local
7755 list<Absyn.EquationItem> eqs;
7756 list<Absyn.ClassPart> xs;
7757 Integer c1, c2, res;
7758 case Absyn.INITIALEQUATIONS(contents = eqs) :: xs
7759 algorithm
7760 ✗ c1 := getEquationItemsCountInEquationItems(eqs);
7761 c2 := getInitialEquationItemsCountInClassParts(xs);
7762 then
7763 c1 + c2;
7764 case _ :: xs
7765 algorithm
7766 ✗ res := getInitialEquationItemsCountInClassParts(xs);
7767 then
7768 res;
7769 case {} then 0;
7770 end match;
7771 end getInitialEquationItemsCountInClassParts;
7772
7773 protected function getNthInitialEquationItem
7774 "Returns the Nth Initial Equation Item from a class."
7775 input Absyn.Class inClass;
7776 input Integer inInteger;
7777 output String outString;
7778 protected
7779 list<Absyn.ClassPart> parts;
7780 algorithm
7781 outString := match inClass
7782 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
7783 ✗ then getNthInitialEquationItemInClassParts(parts,inInteger);
7784 // check also the case model extends X end X;
7785 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
7786 ✗ then getNthInitialEquationItemInClassParts(parts,inInteger);
7787 end match;
7788 end getNthInitialEquationItem;
7789
7790 protected function getNthInitialEquationItemInClassParts
7791 "Helper function to getNthInitialEquationItem"
7792 input list<Absyn.ClassPart> inAbsynClassPartLst;
7793 input Integer inInteger;
7794 output String outString;
7795 algorithm
7796 outString := matchcontinue inAbsynClassPartLst
7797 local
7798 list<Absyn.EquationItem> eqs;
7799 list<Absyn.ClassPart> xs;
7800 Integer c1,newn;
7801 case Absyn.INITIALEQUATIONS(contents = eqs) :: _
7802 ✗ then getNthEquationItemInEquations(eqs, inInteger);
7803 case Absyn.INITIALEQUATIONS(contents = eqs) :: xs /* The rule above failed, subtract the number of equations in the first section and try with the rest of the classparts */
7804 algorithm
7805 ✗ c1 := getEquationItemsCountInEquationItems(eqs);
7806 ✗ newn := inInteger - c1;
7807 ✗ then
7808 getNthInitialEquationItemInClassParts(xs, newn);
7809 case _ :: xs
7810 ✗ then getNthInitialEquationItemInClassParts(xs, inInteger);
7811 end matchcontinue;
7812 end getNthInitialEquationItemInClassParts;
7813
7814 protected function getAnnotationCount
7815 "Counts the number of Annotation sections in a class."
7816 input Absyn.Class inClass;
7817 output Integer outInteger;
7818 algorithm
7819 outInteger := match inClass
7820 local
7821 list<Absyn.Annotation> ann;
7822 case Absyn.CLASS(body = Absyn.PARTS(ann = ann))
7823 ✗ then listLength(ann);
7824 // check also the case model extends X end X;
7825 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(ann = ann))
7826 ✗ then listLength(ann);
7827 case Absyn.CLASS(body = Absyn.DERIVED()) then 0;
7828 end match;
7829 end getAnnotationCount;
7830
7831 protected function getNthAnnotationString
7832 "Returns the Nth Annotation String from a class."
7833 input Absyn.Class inClass;
7834 input Integer inInteger;
7835 output String outString;
7836 algorithm
7837 outString := match (inClass,inInteger)
7838 local
7839 list<Absyn.Annotation> anns;
7840 Absyn.Annotation ann;
7841 String str;
7842 Integer n;
7843 case (Absyn.CLASS(body = Absyn.PARTS(ann = anns)),n)
7844 algorithm
7845 ✗ ann := listGet(anns,n);
7846 ✗ str := Dump.unparseAnnotation(ann);
7847 ✗ str := stringAppend(str, ";");
7848 ✗ str := System.trim(str, " ");
7849 then
7850 str;
7851 // check also the case model extends X end X;
7852 case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(ann = anns)),n)
7853 algorithm
7854 ✗ ann := listGet(anns,n);
7855 ✗ str := Dump.unparseAnnotation(ann);
7856 ✗ str := stringAppend(str, ";");
7857 ✗ str := System.trim(str, " ");
7858 then
7859 str;
7860 end match;
7861 end getNthAnnotationString;
7862
7863 protected function getImportCount
7864 "Counts the number of Import sections in a class."
7865 input Absyn.Class inClass;
7866 output Integer outInteger;
7867 protected
7868 list<Absyn.Import> pub_imports_list , pro_imports_list;
7869 algorithm
7870 ✗ (pub_imports_list , pro_imports_list) := CevalScript.getImportList(inClass);
7871 ✗ outInteger := listLength(pub_imports_list) + listLength(pro_imports_list);
7872 end getImportCount;
7873
7874
7875 protected function getNthImport
7876 "Returns the Nth Import String from a class."
7877 input Absyn.Class inClass;
7878 input Integer inInteger;
7879 output list<Values.Value> outValue;
7880 protected
7881 list<Absyn.Import> pub_imports_list , pro_imports_list;
7882 algorithm
7883 ✗ (pub_imports_list, pro_imports_list) := CevalScript.getImportList(inClass);
7884 ✗ outValue := unparseNthImport(listGet(pub_imports_list,inInteger));
7885 end getNthImport;
7886
7887 protected function unparseNthImport
7888 " helperfunction to getNthImport."
7889 input Absyn.Import inImport;
7890 output list<Values.Value> outValue;
7891 algorithm
7892 outValue := match inImport
7893 local
7894 list<Values.Value> vals;
7895 list<Absyn.GroupImport> gi;
7896 String path_str,id;
7897 Absyn.Path path;
7898 case Absyn.NAMED_IMPORT(name = id,path = path)
7899 algorithm
7900 ✗ path_str := AbsynUtil.pathString(path);
7901 ✗ vals := {Values.STRING(path_str),Values.STRING(id),Values.STRING("named")};
7902 then
7903 vals;
7904 case Absyn.QUAL_IMPORT(path = path)
7905 algorithm
7906 ✗ path_str := AbsynUtil.pathString(path);
7907 ✗ vals := {Values.STRING(path_str),Values.STRING(""),Values.STRING("qualified")};
7908 then
7909 vals;
7910 case Absyn.UNQUAL_IMPORT(path = path)
7911 algorithm
7912 ✗ path_str := AbsynUtil.pathString(path);
7913 ✗ path_str := stringAppendList({path_str, ".*"});
7914 ✗ vals := {Values.STRING(path_str),Values.STRING(""),Values.STRING("unqualified")};
7915 then
7916 vals;
7917 case Absyn.GROUP_IMPORT(prefix = path, groups = gi)
7918 algorithm
7919 ✗ path_str := AbsynUtil.pathString(path);
7920 ✗ id := stringDelimitList(unparseGroupImport(gi),",");
7921 ✗ path_str := stringAppendList({path_str,".{",id,"}"});
7922 ✗ vals := {Values.STRING(path_str),Values.STRING(""),Values.STRING("multiple")};
7923 then
7924 vals;
7925 end match;
7926 end unparseNthImport;
7927
7928 protected function unparseGroupImport
7929 input list<Absyn.GroupImport> inAbsynGroupImportLst;
7930 output list<String> outList;
7931 algorithm
7932 outList := match inAbsynGroupImportLst
7933 local
7934 list<Absyn.GroupImport> rest;
7935 list<String> lst;
7936 String str;
7937 case {} then {};
7938 case Absyn.GROUP_IMPORT_NAME(name = str) :: rest
7939 algorithm
7940 ✗ lst := unparseGroupImport(rest);
7941 then
7942 (str::lst);
7943 case _ :: rest
7944 algorithm
7945 ✗ lst := unparseGroupImport(rest);
7946 then
7947 lst;
7948 end match;
7949 end unparseGroupImport;
7950
7951 public function isShortDefinition
7952 "@auhtor:adrpo
7953 returns true if the class is derived or false otherwise"
7954 input Absyn.Path inPath;
7955 input Absyn.Program inProgram;
7956 output Boolean outBoolean;
7957 algorithm
7958 try
7959 ✗ Absyn.CLASS(body = Absyn.DERIVED()) := ProgramUtil.getPathedClassInProgram(inPath, inProgram);
7960 outBoolean := true;
7961 else
7962 outBoolean := false;
7963 end try;
7964 end isShortDefinition;
7965
7966 protected function isExperiment
7967 input Absyn.Path path;
7968 input Absyn.Program program;
7969 output Boolean res;
7970 protected
7971 Absyn.Class cdef;
7972 algorithm
7973 try
7974 8 cdef := ProgramUtil.getPathedClassInProgram(path, program);
7975
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 7 times.
8 false := AbsynUtil.isPartial(cdef);
7976
4/4
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 4 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 2 times.
7 true := AbsynUtil.isModel(cdef) or AbsynUtil.isBlock(cdef);
7977
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 4 times.
5 SOME(res) := AbsynUtil.getNamedAnnotationInClass(cdef, Absyn.Path.IDENT("experiment"), hasStopTime);
7978 else
7979 res := false;
7980 end try;
7981 end isExperiment;
7982
7983 protected function hasStopTime "For use with getNamedAnnotationExp"
7984 input Option<Absyn.Modification> mod;
7985 output Boolean b;
7986 algorithm
7987 b := match mod
7988 local
7989 list<Absyn.ElementArg> arglst;
7990 case SOME(Absyn.CLASSMOD(elementArgLst = arglst))
7991 4 then List.any(arglst,hasStopTime2);
7992
7993 end match;
7994 end hasStopTime;
7995
7996 protected function hasStopTime2 "For use with getNamedAnnotationExp"
7997 input Absyn.ElementArg arg;
7998 output Boolean b;
7999 algorithm
8000 b := match arg
8001 local
8002
8003 case Absyn.MODIFICATION(path=Absyn.IDENT(name="StopTime")) then true;
8004 else false;
8005
8006 end match;
8007 end hasStopTime2;
8008
8009 protected function searchClassNames
8010 input list<Values.Value> inVals;
8011 input String inSearchText;
8012 input Boolean inFindInText;
8013 input Absyn.Program inProgram;
8014 output list<Values.Value> outVals;
8015 algorithm
8016 outVals := matchcontinue (inVals, inSearchText, inFindInText, inProgram)
8017 local
8018 list<Values.Value> valsList;
8019 String str, str1;
8020 Boolean b;
8021 Absyn.Program p, p1;
8022 Absyn.Class absynClass;
8023 Integer position;
8024 list<Values.Value> xs;
8025 Values.Value val;
8026 case ((val as Values.CODE(_)) :: xs, str1, true, p)
8027 algorithm
8028 ✗ absynClass := ProgramUtil.getPathedClassInProgram(ValuesUtil.getPath(val), p);
8029 ✗ p1 := Absyn.PROGRAM({absynClass},Absyn.TOP());
8030 /* Don't consider packages for FindInText search */
8031 ✗ false := Interactive.isPackage(ValuesUtil.getPath(val), inProgram);
8032 ✗ str := Dump.unparseStr(p1, false);
8033 ✗ position := System.stringFind(System.tolower(str), System.tolower(str1));
8034 ✗ true := (position > -1);
8035 ✗ valsList := searchClassNames(xs, str1, true, p);
8036 then
8037 val::valsList;
8038 case ((val as Values.CODE(_)) :: xs, str1, b, p)
8039 algorithm
8040 ✗ str := ValuesDump.valString(val);
8041 ✗ position := System.stringFind(System.tolower(str), System.tolower(str1));
8042 ✗ true := (position > -1);
8043 ✗ valsList := searchClassNames(xs, str1, b, p);
8044 then
8045 val::valsList;
8046 case ((_ :: xs), str1, b, p)
8047 algorithm
8048 ✗ valsList := searchClassNames(xs, str1, b, p);
8049 then
8050 valsList;
8051 case ({}, _, _, _) then {};
8052 end matchcontinue;
8053 end searchClassNames;
8054
8055 protected function makeUsesArray
8056 input tuple<Absyn.Path,String,list<String>,Boolean> inTpl;
8057 output Values.Value v;
8058 algorithm
8059 v := match inTpl
8060 local
8061 Absyn.Path p;
8062 String pstr,ver;
8063 case (p,_,{ver},_)
8064 algorithm
8065 ✗ pstr := AbsynUtil.pathString(p);
8066 ✗ then ValuesMake.makeArray({Values.STRING(pstr),Values.STRING(ver)});
8067 else
8068 algorithm
8069 ✗ Error.addMessage(Error.INTERNAL_ERROR,{"makeUsesArray failed"});
8070 ✗ then fail();
8071 end match;
8072 end makeUsesArray;
8073
8074 protected function saveTotalModel
8075 input String filename;
8076 input Absyn.Path classpath;
8077 input Boolean stripAnnotations;
8078 input Boolean stripComments;
8079 input Boolean obfuscate;
8080 input Boolean previous = false "Use previousGetTotalModel.";
8081 protected
8082 String result, obfuscate_map;
8083 algorithm
8084
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 4 times.
5 if previous then
8085 1 (result, obfuscate_map) := previousGetTotalModel(classpath, stripAnnotations, stripComments, obfuscate);
8086 else
8087 4 (result, obfuscate_map) := getTotalModel(classpath, stripAnnotations, stripComments, obfuscate);
8088 end if;
8089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if obfuscate then
8090 ✗ System.writeFile(StringUtil.stripFileExtension(filename) + "_mapping.json", obfuscate_map);
8091 end if;
8092 5 System.writeFile(filename, result);
8093 end saveTotalModel;
8094
8095 protected function getTotalModel
8096 input Absyn.Path classpath;
8097 input Boolean stripAnnotations;
8098 input Boolean stripComments;
8099 input Boolean obfuscate;
8100 output String result;
8101 output String obfuscate_map = "";
8102 protected
8103 SCode.Program scodeP;
8104 String str1,str2,str3;
8105 SCode.Element cls;
8106 SCode.Comment cmt;
8107 Absyn.Path cls_path = classpath;
8108 Boolean extendable;
8109 algorithm
8110 4 loadProgram(cls_path);
8111 4 (scodeP, cls) := getTotalProgramNF(cls_path);
8112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 SCode.CLASS(cmt = cmt) := cls;
8113 // A model can't extend a package or a function, those get no _total model.
8114
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
4 extendable := not (SCodeUtil.isPackage(cls) or SCodeUtil.isFunction(cls));
8115 4 scodeP := SCodeUtil.removeBuiltinsFromTopScope(scodeP);
8116
8117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if stripAnnotations or stripComments then
8118 ✗ scodeP := SCodeUtil.stripCommentsFromProgram(scodeP, stripAnnotations, stripComments);
8119 end if;
8120
8121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if obfuscate then
8122 ✗ (scodeP, cls_path, cmt, obfuscate_map) := Obfuscate.obfuscateProgram(scodeP, cls_path, cmt);
8123 end if;
8124
8125 4 result := SCodeDump.programStr(scodeP,SCodeDump.defaultOptions);
8126
8127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if extendable then
8128 4 str1 := AbsynUtil.pathLastIdent(cls_path) + "_total";
8129
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 str2 := if stripComments then "" else SCodeDump.printCommentStr(cmt);
8130
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
4 str2 := if stringEq(str2,"") then "" else (" " + str2);
8131
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 str3 := if stripAnnotations then "" else SCodeDump.printAnnotationStr(cmt,SCodeDump.defaultOptions);
8132
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
4 str3 := if stringEq(str3,"") then "" else (str3 + ";\n");
8133 4 result := result + "\nmodel " + str1 + str2 + "\n extends " + AbsynUtil.pathString(cls_path) + ";\n" + str3 + "end " + str1 + ";\n";
8134 end if;
8135 end getTotalModel;
8136
8137 protected function previousGetTotalModel
8138 "The previous implementation of getTotalModel, which finds the used classes
8139 with NFSCodeFlatten. Kept for comparison by previous_saveTotalModel."
8140 input Absyn.Path classpath;
8141 input Boolean stripAnnotations;
8142 input Boolean stripComments;
8143 input Boolean obfuscate;
8144 output String result;
8145 output String obfuscate_map = "";
8146 protected
8147 SCode.Program scodeP;
8148 String str,str1,str2,str3;
8149 NFSCodeEnv.Env env;
8150 SCode.Comment cmt;
8151 Absyn.Path cls_path = classpath;
8152 algorithm
8153 1 loadProgram(cls_path);
8154 1 scodeP := SymbolTable.getSCode();
8155 1 (scodeP, env) := NFSCodeFlatten.flattenClassInProgram(cls_path, scodeP);
8156
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
1 (NFSCodeEnv.CLASS(cls=SCode.CLASS(cmt=cmt)),_,_) := NFSCodeLookup.lookupClassName(cls_path, env, Absyn.dummyInfo);
8157 1 scodeP := SCodeUtil.removeBuiltinsFromTopScope(scodeP);
8158
8159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if stripAnnotations or stripComments then
8160 ✗ scodeP := SCodeUtil.stripCommentsFromProgram(scodeP, stripAnnotations, stripComments);
8161 end if;
8162
8163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if obfuscate then
8164 ✗ (scodeP, cls_path, cmt, obfuscate_map) := Obfuscate.obfuscateProgram(scodeP, cls_path, cmt);
8165 end if;
8166
8167 1 str := SCodeDump.programStr(scodeP,SCodeDump.defaultOptions);
8168 1 str1 := AbsynUtil.pathLastIdent(cls_path) + "_total";
8169
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 str2 := if stripComments then "" else SCodeDump.printCommentStr(cmt);
8170
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
1 str2 := if stringEq(str2,"") then "" else (" " + str2);
8171
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 str3 := if stripAnnotations then "" else SCodeDump.printAnnotationStr(cmt,SCodeDump.defaultOptions);
8172
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
1 str3 := if stringEq(str3,"") then "" else (str3 + ";\n");
8173 1 str1 := "\nmodel " + str1 + str2 + "\n extends " + AbsynUtil.pathString(cls_path) + ";\n" + str3 + "end " + str1 + ";\n";
8174 1 result := str + str1;
8175 end previousGetTotalModel;
8176
8177 protected function getTotalProgramNF
8178 "Returns the loaded program reduced to the given class and what it uses. The
8179 class is kept whole, and the names in it, in every class declared in it and
8180 in everything they use are looked up with the new frontend to find what they
8181 use, without instantiating them. That also works for packages and for
8182 classes that can't be instantiated."
8183 input Absyn.Path classPath;
8184 output SCode.Program program;
8185 output SCode.Element cls "The class as saved.";
8186 protected
8187 UnorderedSet<String> used;
8188 Boolean nf_inst;
8189 SCode.Program builtin_p, annotation_p;
8190 algorithm
8191 4 cls := InteractiveUtil.getPathedSCodeElementInProgram(classPath, SymbolTable.getSCode());
8192
8193 // Only the used elements are wanted from the lookups, not their messages.
8194 4 ErrorExt.setCheckpoint(getInstanceName());
8195 // The new frontend needs its own builtin classes, also with -d=nonewInst.
8196 4 nf_inst := FlagsUtil.set(Flags.SCODE_INST, true);
8197
8198 try
8199 4 (_, builtin_p) := FBuiltin.getInitialFunctions();
8200 4 annotation_p := AbsynToSCode.translateAbsyn2SCode(
8201 InteractiveUtil.modelicaAnnotationProgram(Config.getAnnotationVersion()));
8202 8 used := NFUsedElements.collect(classPath :: getNestedClassPaths(cls, classPath),
8203 listAppend(builtin_p, SymbolTable.getSCode()), annotation_p);
8204 else
8205 ✗ used := UnorderedSet.new<String>(stringHashDjb2, stringEq);
8206 end try;
8207
8208 4 FlagsUtil.set(Flags.SCODE_INST, nf_inst);
8209 4 ErrorExt.rollBack(getInstanceName());
8210 4 markElementUsed(cls, used);
8211
8212 // Lookups may have loaded libraries, so fetch the program afterwards.
8213 4 program := SymbolTable.getSCode();
8214 4 program := filterUsedClasses(program, used, program);
8215 4 cls := InteractiveUtil.getPathedSCodeElementInProgram(classPath, program);
8216 end getTotalProgramNF;
8217
8218 protected function getDefUseChains
8219 "Returns the def-use chains of the names in a class as JSON, or writes them
8220 to a file and returns its name."
8221 input Absyn.Path className "A class, or a component declared in a class.";
8222 input String fileName;
8223 input Absyn.Path scope "The class to look for the uses in, or AllLoadedClasses.";
8224 input Boolean prettyPrint;
8225 output String result;
8226 protected
8227 Absyn.Path cls_path = className;
8228 list<Absyn.Path> paths = {};
8229 SCode.Program program;
8230 SCode.Element cls;
8231 list<NFUsedElements.Definition> defs;
8232 list<NFUsedElements.Use> uses, unresolved;
8233 algorithm
8234 18 program := SymbolTable.getSCode();
8235
8236 // A component gives the chain of the component, the class it's declared in is walked.
8237 try
8238 18 cls := InteractiveUtil.getPathedSCodeElementInProgram(className, program);
8239
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 3 times.
14 if not SCodeUtil.elementIsClass(cls) then
8240 11 cls_path := AbsynUtil.stripLast(className);
8241 end if;
8242 else
8243 4 cls_path := AbsynUtil.stripLast(className);
8244 end try;
8245
8246 18 paths := scopeClassPaths(scope, program);
8247
8248
4/4
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 15 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 2 times.
18 if not isAllLoadedClasses(scope) and not AbsynUtil.pathPrefixOf(scope, cls_path) then
8249 try
8250 1 cls := InteractiveUtil.getPathedSCodeElementInProgram(cls_path, program);
8251 1 paths := getNestedClassPaths(cls, cls_path, cls_path :: paths);
8252 else
8253 end try;
8254 end if;
8255
8256 18 (defs, uses, unresolved) := collectDefUse(paths, program);
8257
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 15 times.
18 result := NFDefUseChains.toJSON(AbsynUtil.pathString(className), defs, uses, unresolved,
8258 if isAllLoadedClasses(scope) then "" else AbsynUtil.pathString(scope), prettyPrint);
8259
8260
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if not stringEmpty(fileName) then
8261 2 System.writeFile(fileName, result);
8262 result := fileName;
8263 end if;
8264 end getDefUseChains;
8265
8266 protected function getClassDiagram
8267 "Returns a UML class diagram of a class, see NFClassDiagram, or writes it to a
8268 file and returns its name."
8269 input Absyn.Path className;
8270 input String fileName;
8271 input String format;
8272 input Integer depth;
8273 input list<String> exclude;
8274 input Boolean showModifiers;
8275 output String result = "";
8276 protected
8277 SCode.Program program, builtin_p, annotation_p;
8278 Boolean nf_inst;
8279 algorithm
8280
7/12
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 time.
✓ Branch 11 taken 1 time.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 time.
7 if format <> "plantuml" and format <> "mermaid" and format <> "drawio" then
8281 1 Error.addCompilerError("getClassDiagram: unknown format " + format + ", expected plantuml, mermaid or drawio.");
8282 1 return;
8283 end if;
8284
8285 6 program := SymbolTable.getSCode();
8286
8287 try
8288 6 _ := InteractiveUtil.getPathedSCodeElementInProgram(className, program);
8289 else
8290 2 Error.addMessage(Error.LOOKUP_ERROR, {AbsynUtil.pathString(className), "<TOP>"});
8291 1 return;
8292 end try;
8293
8294 // Only the uses are wanted from the lookups, not their messages, see collectDefUse.
8295 5 ErrorExt.setCheckpoint(getInstanceName());
8296 5 nf_inst := FlagsUtil.set(Flags.SCODE_INST, true);
8297
8298 try
8299 5 (_, builtin_p) := FBuiltin.getInitialFunctions();
8300 5 annotation_p := AbsynToSCode.translateAbsyn2SCode(
8301 InteractiveUtil.modelicaAnnotationProgram(Config.getAnnotationVersion()));
8302 5 result := NFClassDiagram.generate(className, listAppend(builtin_p, program), annotation_p,
8303 format, depth, exclude, showModifiers);
8304 else
8305 end try;
8306
8307 5 FlagsUtil.set(Flags.SCODE_INST, nf_inst);
8308 5 ErrorExt.rollBack(getInstanceName());
8309
8310
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
5 if not stringEmpty(fileName) and not stringEmpty(result) then
8311 1 System.writeFile(fileName, result);
8312 result := fileName;
8313 end if;
8314 end getClassDiagram;
8315
8316 protected function getDependencyGraph
8317 "Returns the classes in a scope, the hashes of their source and the classes
8318 they use as JSON, or writes it to a file and returns its name."
8319 input Absyn.Path scope "A class, or AllLoadedClasses.";
8320 input String fileName;
8321 input Boolean prettyPrint;
8322 output String result;
8323 protected
8324 SCode.Program program;
8325 list<NFUsedElements.Definition> defs;
8326 list<NFUsedElements.Use> uses;
8327 algorithm
8328 3 program := SymbolTable.getSCode();
8329 3 (defs, uses, _) := collectDefUse(scopeClassPaths(scope, program), program);
8330 3 result := NFDefUseChains.dependencyGraphJSON(AbsynUtil.pathString(scope), defs, uses, prettyPrint);
8331
8332
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 if not stringEmpty(fileName) then
8333 1 System.writeFile(fileName, result);
8334 result := fileName;
8335 end if;
8336 end getDependencyGraph;
8337
8338 protected function getDefinitionAt
8339 "Returns the definition of the name at a position in a file as JSON."
8340 input String fileName;
8341 input Integer line;
8342 input Integer column;
8343 input Boolean prettyPrint;
8344 output String result;
8345 protected
8346 SCode.Program program;
8347 Option<tuple<Absyn.Path, String>> found = NONE();
8348 Absyn.Path path;
8349 String file = fileName, real_path;
8350 list<NFUsedElements.Definition> defs = {};
8351 list<NFUsedElements.Use> uses = {};
8352 algorithm
8353 11 program := SymbolTable.getSCode();
8354 11 real_path := System.realpath(fileName);
8355
8356
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 for c in program loop
8357 11 found := findClassAt(c, Absyn.IDENT(SCodeUtil.elementName(c)), fileName, real_path, line, column, found);
8358 end for;
8359
8360 // The names in the innermost class the position is in are looked up. The
8361 // classes it's in and their class extends and redeclared classes are also
8362 // walked, since those replace what the names are looked up through.
8363
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 if isSome(found) then
8364 11 SOME((path, file)) := found;
8365 22 (defs, uses, _) := collectDefUse(path :: enclosingReplacingClasses(path, program), program);
8366 end if;
8367
8368 11 result := NFDefUseChains.definitionAtJSON(file, line, column, defs, uses, prettyPrint);
8369 end getDefinitionAt;
8370
8371 protected function enclosingReplacingClasses
8372 "Returns the classes a class is in and the class extends and redeclared
8373 classes declared in them, outermost first."
8374 input Absyn.Path path;
8375 input SCode.Program program;
8376 output list<Absyn.Path> paths = {};
8377 protected
8378 Absyn.Path p = path;
8379 SCode.Element cls;
8380 algorithm
8381
2/2
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 11 times.
24 while AbsynUtil.pathIsQual(p) loop
8382 13 p := AbsynUtil.stripLast(p);
8383
8384 try
8385 13 cls := InteractiveUtil.getPathedSCodeElementInProgram(p, program);
8386
8387
2/2
✓ Branch 1 taken 139 times.
✓ Branch 2 taken 13 times.
165 for e in SCodeUtil.getClassElements(cls) loop
8388
5/6
✓ Branch 1 taken 138 times.
✓ Branch 2 taken 1 time.
✓ Branch 4 taken 136 times.
✓ Branch 5 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 136 times.
139 if SCodeUtil.elementIsClass(e) and (SCodeUtil.isClassExtends(e) or SCodeUtil.isElementRedeclare(e)) then
8389 2 paths := AbsynUtil.suffixPath(p, SCodeUtil.elementName(e)) :: paths;
8390 end if;
8391 end for;
8392
8393 paths := p :: paths;
8394 else
8395 end try;
8396 end while;
8397 end enclosingReplacingClasses;
8398
8399 protected function findClassAt
8400 "Finds the innermost class declared in a file that a position is in, and the
8401 name of the file as the class has it."
8402 input SCode.Element element;
8403 input Absyn.Path path;
8404 input String fileName;
8405 input String realPath "fileName with a full path.";
8406 input Integer line;
8407 input Integer column;
8408 input output Option<tuple<Absyn.Path, String>> found;
8409 protected
8410 SourceInfo info;
8411 algorithm
8412
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 275 times.
275 if not SCodeUtil.elementIsClass(element) then
8413 ✗ return;
8414 end if;
8415
8416 275 info := SCodeUtil.elementInfo(element);
8417
8418
11/20
✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 275 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 275 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 158 times.
✓ Branch 11 taken 117 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 158 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 94 times.
✓ Branch 17 taken 23 times.
✓ Branch 18 taken 1 time.
✓ Branch 19 taken 93 times.
✓ Branch 20 taken 1 time.
✗ Branch 21 not taken.
275 if (info.fileName == fileName or info.fileName == realPath) and
8419 (line > info.lineNumberStart or (line == info.lineNumberStart and column >= info.columnNumberStart)) and
8420 (line < info.lineNumberEnd or (line == info.lineNumberEnd and column <= info.columnNumberEnd)) then
8421 24 found := SOME((path, info.fileName));
8422 end if;
8423
8424 // A class in a file of its own is declared in a class in another file.
8425
2/2
✓ Branch 1 taken 583 times.
✓ Branch 2 taken 275 times.
858 for e in SCodeUtil.getClassElements(element) loop
8426
2/2
✓ Branch 1 taken 264 times.
✓ Branch 2 taken 319 times.
583 if SCodeUtil.elementIsClass(e) then
8427 264 found := findClassAt(e, AbsynUtil.suffixPath(path, SCodeUtil.elementName(e)),
8428 fileName, realPath, line, column, found);
8429 end if;
8430 end for;
8431 end findClassAt;
8432
8433 protected function isAllLoadedClasses
8434 input Absyn.Path path;
8435 output Boolean res = AbsynUtil.pathEqual(path, Absyn.Path.IDENT("AllLoadedClasses"));
8436 end isAllLoadedClasses;
8437
8438 protected function scopeClassPaths
8439 "Returns the paths of a class and all classes declared in it, or of all
8440 loaded classes."
8441 input Absyn.Path scope;
8442 input SCode.Program program;
8443 output list<Absyn.Path> paths = {};
8444 protected
8445 SCode.Element cls;
8446 algorithm
8447
2/2
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 6 times.
21 if isAllLoadedClasses(scope) then
8448
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
30 for c in program loop
8449
2/6
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
15 if SCodeUtil.elementIsClass(c) and SCodeUtil.elementName(c) <> "OpenModelica" then
8450 30 paths := getNestedClassPaths(c, Absyn.IDENT(SCodeUtil.elementName(c)),
8451 Absyn.IDENT(SCodeUtil.elementName(c)) :: paths);
8452 end if;
8453 end for;
8454 else
8455 try
8456 6 cls := InteractiveUtil.getPathedSCodeElementInProgram(scope, program);
8457 6 paths := getNestedClassPaths(cls, scope, {scope});
8458 else
8459 end try;
8460 end if;
8461 end scopeClassPaths;
8462
8463 protected function collectDefUse
8464 "Walks the given classes and returns the definitions and uses of the names in
8465 them, see NFUsedElements.collectUses."
8466 input list<Absyn.Path> paths "In reverse order.";
8467 input SCode.Program program;
8468 output list<NFUsedElements.Definition> defs = {};
8469 output list<NFUsedElements.Use> uses = {};
8470 output list<NFUsedElements.Use> unresolved = {};
8471 protected
8472 SCode.Program builtin_p, annotation_p;
8473 Boolean nf_inst;
8474 algorithm
8475 // Only the uses are wanted from the lookups, not their messages.
8476 32 ErrorExt.setCheckpoint(getInstanceName());
8477 // The new frontend needs its own builtin classes, also with -d=nonewInst.
8478 32 nf_inst := FlagsUtil.set(Flags.SCODE_INST, true);
8479
8480 try
8481 32 (_, builtin_p) := FBuiltin.getInitialFunctions();
8482 32 annotation_p := AbsynToSCode.translateAbsyn2SCode(
8483 InteractiveUtil.modelicaAnnotationProgram(Config.getAnnotationVersion()));
8484 32 (defs, uses, unresolved) := NFUsedElements.collectUses(listReverse(paths),
8485 listAppend(builtin_p, program), annotation_p);
8486 else
8487 end try;
8488
8489 32 FlagsUtil.set(Flags.SCODE_INST, nf_inst);
8490 32 ErrorExt.rollBack(getInstanceName());
8491 end collectDefUse;
8492
8493 protected function getNestedClassPaths
8494 "Returns the paths of all classes declared in a class, at any depth."
8495 input SCode.Element cls;
8496 input Absyn.Path clsPath;
8497 input output list<Absyn.Path> paths = {};
8498 protected
8499 Absyn.Path path;
8500 algorithm
8501
2/2
✓ Branch 1 taken 373 times.
✓ Branch 2 taken 135 times.
508 for e in SCodeUtil.getClassElements(cls) loop
8502
2/2
✓ Branch 1 taken 109 times.
✓ Branch 2 taken 264 times.
373 if SCodeUtil.elementIsClass(e) then
8503 109 path := AbsynUtil.suffixPath(clsPath, SCodeUtil.elementName(e));
8504 109 paths := getNestedClassPaths(e, path, path :: paths);
8505 end if;
8506 end for;
8507 end getNestedClassPaths;
8508
8509 protected function markElementUsed
8510 "Adds an element and everything declared in it to the used set."
8511 input SCode.Element element;
8512 input UnorderedSet<String> used;
8513 algorithm
8514 22 UnorderedSet.add(NFUsedElements.elementKey(element), used);
8515
8516
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 6 times.
22 if SCodeUtil.elementIsClass(element) then
8517
2/2
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 6 times.
25 for e in SCodeUtil.getClassElements(element) loop
8518
4/4
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 2 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 1 time.
19 if SCodeUtil.elementIsClass(e) or SCodeUtil.isComponent(e) then
8519 18 markElementUsed(e, used);
8520 end if;
8521 end for;
8522 end if;
8523 end markElementUsed;
8524
8525 protected function filterUsedClasses
8526 "Removes the classes that aren't in the used set from a list of elements,
8527 also from the classes that are kept. Components are only removed from
8528 packages, where they are constants that may or may not be used."
8529 input list<SCode.Element> elements;
8530 input UnorderedSet<String> used;
8531 input SCode.Program program "The whole program, to resolve imports in.";
8532 input Boolean inPackage = false;
8533 output list<SCode.Element> outElements = {};
8534 algorithm
8535
2/2
✓ Branch 0 taken 3665 times.
✓ Branch 1 taken 236 times.
3901 for e in elements loop
8536
2/2
✓ Branch 1 taken 1259 times.
✓ Branch 2 taken 2406 times.
3665 if SCodeUtil.elementIsClass(e) then
8537
2/2
✓ Branch 2 taken 321 times.
✓ Branch 3 taken 938 times.
1259 if UnorderedSet.contains(NFUsedElements.elementKey(e), used) then
8538 321 outElements := filterUsedNestedClasses(e, used, program) :: outElements;
8539 end if;
8540 elseif inPackage and SCodeUtil.isComponent(e) then
8541
2/2
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 1294 times.
1348 if UnorderedSet.contains(NFUsedElements.elementKey(e), used) then
8542 outElements := e :: outElements;
8543 end if;
8544 elseif not isUnusedImport(e, used, program) then
8545 outElements := e :: outElements;
8546 end if;
8547 end for;
8548
8549 236 outElements := listReverse(outElements);
8550 end filterUsedClasses;
8551
8552 protected function filterUsedNestedClasses
8553 input output SCode.Element cls;
8554 input UnorderedSet<String> used;
8555 input SCode.Program program;
8556 algorithm
8557 () := match cls
8558 case SCode.CLASS()
8559 algorithm
8560 321 cls.classDef := filterUsedClassDef(cls.classDef, used, program, SCodeUtil.isPackage(cls));
8561 then
8562 ();
8563
8564 else ();
8565 end match;
8566 end filterUsedNestedClasses;
8567
8568 protected function filterUsedClassDef
8569 input output SCode.ClassDef classDef;
8570 input UnorderedSet<String> used;
8571 input SCode.Program program;
8572 input Boolean inPackage;
8573 algorithm
8574 () := match classDef
8575 case SCode.PARTS()
8576 algorithm
8577 232 classDef.elementLst := filterUsedClasses(classDef.elementLst, used, program, inPackage);
8578 then
8579 ();
8580
8581 case SCode.CLASS_EXTENDS()
8582 algorithm
8583 17 classDef.composition := filterUsedClassDef(classDef.composition, used, program, inPackage);
8584 then
8585 ();
8586
8587 else ();
8588 end match;
8589 end filterUsedClassDef;
8590
8591 protected function isUnusedImport
8592 "Returns true for an import of a single element that is declared in the
8593 program but wasn't used. Imports are only resolved when a name is looked up
8594 through them, so the import of a used element has recorded it."
8595 input SCode.Element element;
8596 input UnorderedSet<String> used;
8597 input SCode.Program program;
8598 output Boolean unused;
8599 protected
8600 Absyn.Path path;
8601 algorithm
8602 unused := match element
8603 case SCode.IMPORT(imp = Absyn.Import.NAMED_IMPORT(path = path))
8604 6 then isUnusedElementPath(path, used, program);
8605 case SCode.IMPORT(imp = Absyn.Import.QUAL_IMPORT(path = path))
8606 41 then isUnusedElementPath(path, used, program);
8607 else false;
8608 end match;
8609 end isUnusedImport;
8610
8611 protected function isUnusedElementPath
8612 input Absyn.Path path;
8613 input UnorderedSet<String> used;
8614 input SCode.Program program;
8615 output Boolean unused;
8616 algorithm
8617 try
8618 47 unused := not UnorderedSet.contains(NFUsedElements.elementKey(
8619 InteractiveUtil.getPathedSCodeElementInProgram(path, program)), used);
8620 else
8621 // Not declared where the path points, e.g. inherited. Keep the import.
8622 unused := false;
8623 end try;
8624 end isUnusedElementPath;
8625
8626 protected function saveTotalModelDebug
8627 input String filename;
8628 input Absyn.Path classPath;
8629 input Boolean stripAnnotations;
8630 input Boolean stripComments;
8631 input Boolean obfuscate;
8632 protected
8633 SCode.Program prog;
8634 String str, str1, str2, str3;
8635 Absyn.Path cls_path = classPath;
8636 Option<SCode.Comment> ocmt;
8637 SCode.Comment cmt;
8638 algorithm
8639 ✗ loadProgram(cls_path);
8640 ✗ prog := SymbolTable.getSCode();
8641 ✗ prog := TotalModelDebug.getTotalModel(prog, cls_path);
8642 ✗ prog := SCodeUtil.removeBuiltinsFromTopScope(prog);
8643 ✗ ocmt := SCodeUtil.getElementComment(InteractiveUtil.getPathedSCodeElementInProgram(cls_path, prog));
8644 ✗ cmt := if isSome(ocmt) then Util.getOption(ocmt) else SCode.noComment;
8645
8646 ✗ if stripAnnotations or stripComments then
8647 ✗ prog := SCodeUtil.stripCommentsFromProgram(prog, stripAnnotations, stripComments);
8648 end if;
8649
8650 ✗ if obfuscate then
8651 ✗ (prog, cls_path, cmt, _) := Obfuscate.obfuscateProgram(prog, cls_path, cmt);
8652 end if;
8653
8654 ✗ str := SCodeDump.programStr(prog, SCodeDump.defaultOptions);
8655 ✗ str1 := AbsynUtil.pathLastIdent(cls_path) + "_total";
8656 ✗ str2 := if stripComments then "" else SCodeDump.printCommentStr(cmt);
8657 ✗ str2 := if stringEq(str2,"") then "" else (" " + str2);
8658 ✗ str3 := if stripAnnotations then "" else SCodeDump.printAnnotationStr(cmt,SCodeDump.defaultOptions);
8659 ✗ str3 := if stringEq(str3,"") then "" else (str3 + ";\n");
8660 ✗ str1 := "\nmodel " + str1 + str2 + "\n extends " + AbsynUtil.pathString(cls_path) + ";\n" + str3 + "end " + str1 + ";\n";
8661 ✗ System.writeFile(filename, str + str1);
8662 end saveTotalModelDebug;
8663
8664 protected function getDymolaStateAnnotation
8665 "Returns the __Dymola_state annotation of a class.
8666 This is annotated with the annotation:
8667 annotation (__Dymola_state=true); in the class definition"
8668 input Absyn.Path className;
8669 input Absyn.Program p;
8670 output Boolean isState;
8671 algorithm
8672 isState := match p
8673 local
8674 String stateStr;
8675 case _
8676 algorithm
8677 6 stateStr := ProgramUtil.getNamedAnnotationExp(className, p, Absyn.IDENT("__Dymola_state"), SOME("false"), getDymolaStateAnnotationModStr);
8678
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 then
8679 stringEq(stateStr, "true");
8680 end match;
8681 end getDymolaStateAnnotation;
8682
8683 protected function getDymolaStateAnnotationModStr
8684 "Extractor function for getDymolaStateAnnotation"
8685 input Option<Absyn.Modification> mod;
8686 output String stateStr;
8687 algorithm
8688 stateStr := matchcontinue mod
8689 local Absyn.Exp e;
8690
8691 case SOME(Absyn.CLASSMOD(eqMod = Absyn.EQMOD(exp=e)))
8692 algorithm
8693 ✗ stateStr := Dump.printExpStr(e);
8694 then
8695 stateStr;
8696
8697 else "false";
8698
8699 end matchcontinue;
8700 end getDymolaStateAnnotationModStr;
8701
8702 protected function getClassInformation
8703 "author: PA
8704 Returns all the possible class information.
8705 changed by adrpo 2006-02-24 (latest 2006-03-14) to return more info and in a different format:
8706 {\"restriction\",\"comment\",\"filename.mo\",{bool,bool,bool},{\"readonly|writable\",int,int,int,int}}
8707 if you like more named attributes, use getClassAttributes API which uses get_class_attributes function
8708 change by sjoelund.se 2014-11-14 to actually be sane. Using the typed API.
8709 "
8710 input Absyn.Path path;
8711 input Absyn.Program p;
8712 output Values.Value res_1;
8713 protected
8714 String name,file,res,cmt,version,preferredView,access,versionDate,versionBuild,dateModified,revisionId;
8715 String lastIdent;
8716 Boolean partialPrefix,finalPrefix,encapsulatedPrefix,isReadOnly,isProtectedClass,isDocClass,isState;
8717 Absyn.Restriction restr;
8718 Absyn.ClassDef cdef;
8719 Integer sl,sc,el,ec;
8720 Absyn.Path classPath;
8721 algorithm
8722 6 Absyn.CLASS(name,partialPrefix,finalPrefix,encapsulatedPrefix,restr,cdef,_,_,_,SOURCEINFO(file,isReadOnly,sl,sc,el,ec,_)) := ProgramUtil.getPathedClassInProgram(path, p);
8723 6 res := Dump.unparseRestrictionStr(restr);
8724 6 cmt := getClassDefComment(cdef);
8725 6 file := Testsuite.friendly(file);
8726
2/2
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
6 if AbsynUtil.pathIsIdent(AbsynUtil.makeNotFullyQualified(path)) then
8727 isProtectedClass := false;
8728 else
8729 4 lastIdent := AbsynUtil.pathLastIdent(AbsynUtil.makeNotFullyQualified(path));
8730 4 classPath := AbsynUtil.stripLast(path);
8731 4 isProtectedClass := Interactive.isProtectedClass(classPath, lastIdent, p);
8732 end if;
8733 6 isDocClass := Interactive.getDocumentationClassAnnotation(path, p);
8734 6 version := CevalScript.getPackageVersion(path, p);
8735 6 preferredView := Interactive.getStringNamedAnnotation(path, p, Absyn.IDENT("preferredView"));
8736 6 isState := getDymolaStateAnnotation(path, p);
8737 6 access := Interactive.getAccessAnnotation(path, p);
8738 6 versionDate := Interactive.getStringNamedAnnotation(path, p, Absyn.IDENT("versionDate"));
8739 6 versionBuild := Interactive.getIntegerNamedAnnotation(path, p, Absyn.IDENT("versionBuild"));
8740 6 dateModified := Interactive.getStringNamedAnnotation(path, p, Absyn.IDENT("dateModified"));
8741 6 revisionId := Interactive.getStringNamedAnnotation(path, p, Absyn.IDENT("revisionId"));
8742
7/14
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✓ Branch 19 taken 6 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 6 times.
✗ Branch 23 not taken.
✓ Branch 27 taken 6 times.
✗ Branch 28 not taken.
60 res_1 := Values.TUPLE({
8743 Values.STRING(res),
8744 Values.STRING(cmt),
8745 Values.BOOL(partialPrefix),
8746 Values.BOOL(finalPrefix),
8747 Values.BOOL(encapsulatedPrefix),
8748 Values.STRING(file),
8749 Values.BOOL(isReadOnly),
8750 Values.INTEGER(sl),
8751 Values.INTEGER(sc),
8752 Values.INTEGER(el),
8753 Values.INTEGER(ec),
8754 getClassDimensions(cdef),
8755 Values.BOOL(isProtectedClass),
8756 Values.BOOL(isDocClass),
8757 Values.STRING(version),
8758 Values.STRING(preferredView),
8759 Values.BOOL(isState),
8760 Values.STRING(access),
8761 Values.STRING(versionDate),
8762 Values.STRING(versionBuild),
8763 Values.STRING(dateModified),
8764 Values.STRING(revisionId)
8765 });
8766 end getClassInformation;
8767
8768 function getClassDimensions
8769 "return the dimensions of a class
8770 as vector of dimension sizes in a string.
8771 Note: A class can only have dimensions if it is a short class definition."
8772 input Absyn.ClassDef cdef;
8773 output Values.Value v;
8774 algorithm
8775 v := match cdef
8776 local
8777 Absyn.ArrayDim ad;
8778 case Absyn.DERIVED(typeSpec=Absyn.TPATH(arrayDim=SOME(ad)))
8779 ✗ then ValuesMake.makeArray(list(Values.STRING(Dump.printSubscriptStr(d)) for d in ad));
8780 6 else ValuesMake.makeArray({});
8781 end match;
8782 end getClassDimensions;
8783
8784 function getClassElementComment
8785 "Returns the comment on a class element."
8786 input Absyn.Element element;
8787 output String commentStr;
8788 protected
8789 Absyn.Class cls;
8790 algorithm
8791 commentStr := match element
8792 case Absyn.Element.ELEMENT(specification = Absyn.ElementSpec.CLASSDEF(class_ = cls))
8793 algorithm
8794 // The comment can go either before and/or after the constrainedby clause,
8795 // the one after has higher priority.
8796 ✗ commentStr := InteractiveUtil.getConstrainingClassComment(element.constrainClass);
8797
8798 ✗ if stringEmpty(commentStr) then
8799 ✗ commentStr := getClassDefComment(cls.body);
8800 end if;
8801 then
8802 commentStr;
8803
8804 else "";
8805 end match;
8806 end getClassElementComment;
8807
8808 function getClassDefComment "Returns the class comment of a Absyn.ClassDef"
8809 input Absyn.ClassDef inClassDef;
8810 output String outString;
8811 algorithm
8812 outString:=
8813 match inClassDef
8814 local
8815 String str;
8816 Option<Absyn.Comment> cmt;
8817 case Absyn.PARTS(comment = SOME(str)) then str;
8818 case Absyn.DERIVED(comment = cmt)
8819 ✗ then Interactive.getStringComment(cmt);
8820 case Absyn.ENUMERATION(comment = cmt)
8821 ✗ then Interactive.getStringComment(cmt);
8822 case Absyn.ENUMERATION(comment = cmt)
8823 ✗ then Interactive.getStringComment(cmt);
8824 case Absyn.OVERLOAD(comment = cmt)
8825 ✗ then Interactive.getStringComment(cmt);
8826 case Absyn.CLASS_EXTENDS(comment = SOME(str)) then str;
8827 else "";
8828 end match;
8829 end getClassDefComment;
8830
8831 protected function getAnnotationInEquation
8832 "This function takes an `EquationItem\' and returns a comma separated
8833 string of values from the flat record of an equation annotation that
8834 is found in the `EquationItem\'."
8835 input Absyn.EquationItem inEquationItem;
8836 output String outString;
8837 algorithm
8838 outString := match inEquationItem
8839 local
8840 String annotationStr;
8841 list<String> annotationList;
8842 list<Absyn.ElementArg> annotations;
8843
8844 case Absyn.EQUATIONITEM(comment = SOME(Absyn.COMMENT(SOME(Absyn.ANNOTATION(annotations)),_)))
8845 algorithm
8846 11 annotationList := getAnnotationInEquationElArgs(annotations);
8847 11 annotationStr := stringDelimitList(annotationList, ", ");
8848 then
8849 annotationStr;
8850 case Absyn.EQUATIONITEM(comment = NONE())
8851 then
8852 "";
8853 end match;
8854 end getAnnotationInEquation;
8855
8856 protected function getAnnotationInEquationElArgs
8857 input list<Absyn.ElementArg> inElArgLst;
8858 output list<String> outStringLst;
8859 algorithm
8860 outStringLst := matchcontinue inElArgLst
8861 local
8862 Absyn.FunctionArgs fargs;
8863 list<SCode.Element> p_1;
8864 FCore.Graph env;
8865 DAE.Exp newexp;
8866 String gexpstr, gexpstr_1, annName;
8867 list<String> res;
8868 list<Absyn.ElementArg> mod, rest;
8869 FCore.Cache cache;
8870 DAE.Properties prop;
8871 Absyn.Program lineProgram;
8872
8873 // handle empty
8874 case {} then {};
8875
8876 case Absyn.MODIFICATION(path = Absyn.IDENT(annName), modification = SOME(Absyn.CLASSMOD(mod,_))) :: rest
8877 algorithm
8878 11 lineProgram := InteractiveUtil.modelicaAnnotationProgram(Config.getAnnotationVersion());
8879 11 fargs := Interactive.createFuncargsFromElementargs(mod);
8880 11 p_1 := AbsynToSCode.translateAbsyn2SCode(lineProgram);
8881 11 (cache,env) := Inst.makeEnvFromProgram(p_1);
8882 11 (_,newexp,prop) := StaticScript.elabGraphicsExp(cache,env, Absyn.CALL(Absyn.CREF_IDENT(annName,{}),fargs,{}), false,DAE.NOPRE(), sourceInfo()) "impl" ;
8883 11 (cache, newexp, prop) := Ceval.cevalIfConstant(cache, env, newexp, prop, false, sourceInfo());
8884 11 Print.clearErrorBuf() "this is to clear the error-msg generated by the annotations." ;
8885 11 gexpstr := ExpressionBasics.printExpStr(newexp);
8886 11 res := getAnnotationInEquationElArgs(rest);
8887 then
8888 (gexpstr :: res);
8889 case Absyn.MODIFICATION(path = Absyn.IDENT(annName), modification = SOME(Absyn.CLASSMOD(_,Absyn.NOMOD()))) :: rest
8890 algorithm
8891 ✗ gexpstr_1 := stringAppendList({annName,"(error)"});
8892 ✗ res := getAnnotationInEquationElArgs(rest);
8893 then
8894 (gexpstr_1 :: res);
8895 end matchcontinue;
8896 end getAnnotationInEquationElArgs;
8897
8898 protected function getTransitions
8899 input Absyn.Path path;
8900 input Absyn.Program p;
8901 output Values.Value res;
8902 protected
8903 list<list<String>> transitions;
8904 Absyn.Class cdef;
8905 algorithm
8906 4 cdef := ProgramUtil.getPathedClassInProgram(path, p);
8907 4 transitions := listReverse(getTransitionsInClass(cdef));
8908 4 res := ValuesMake.makeArray(List.map(transitions, ValuesMake.makeStringArray));
8909 end getTransitions;
8910
8911 protected function getTransitionsInClass
8912 "Gets the list of transitions in a class."
8913 input Absyn.Class inClass;
8914 output list<list<String>> outTransitions;
8915 algorithm
8916 outTransitions := match inClass
8917 local
8918 list<list<String>> transitions;
8919 list<Absyn.ClassPart> parts;
8920
8921 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
8922 algorithm
8923 4 transitions := getTransitionsInClassParts(parts);
8924 then
8925 transitions;
8926
8927 // handle also the case model extends X end X;
8928 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
8929 algorithm
8930 ✗ transitions := getTransitionsInClassParts(parts);
8931 then
8932 transitions;
8933
8934 case Absyn.CLASS(body = Absyn.DERIVED()) then {};
8935
8936 end match;
8937 end getTransitionsInClass;
8938
8939 protected function getTransitionsInClassParts
8940 "Helper function for getTransitionsInClass."
8941 input list<Absyn.ClassPart> inAbsynClassPartLst;
8942 output list<list<String>> outTransitions;
8943 algorithm
8944 outTransitions := matchcontinue inAbsynClassPartLst
8945 local
8946 list<list<String>> transitions1, transitions2;
8947 list<Absyn.EquationItem> eqlist;
8948 list<Absyn.ClassPart> xs;
8949
8950 case Absyn.EQUATIONS(contents = eqlist) :: xs
8951 algorithm
8952 4 transitions1 := getTransitionsInEquations(eqlist, {});
8953 4 transitions2 := getTransitionsInClassParts(xs);
8954 4 then
8955 listAppend(transitions1, transitions2);
8956
8957 case _ :: xs
8958 algorithm
8959 4 transitions1 := getTransitionsInClassParts(xs);
8960 then
8961 transitions1;
8962
8963 case {}
8964 then {};
8965
8966 end matchcontinue;
8967 end getTransitionsInClassParts;
8968
8969 protected function getTransitionsInEquations
8970 "Helper function for getTransitionsInClass."
8971 input list<Absyn.EquationItem> inAbsynEquationItemLst;
8972 input list<list<String>> inTransitions;
8973 output list<list<String>> outTransitions;
8974 algorithm
8975 outTransitions := match (inAbsynEquationItemLst, inTransitions)
8976 local
8977 list<list<String>> transitions;
8978 list<String> transition;
8979 Absyn.EquationItem eqItem;
8980 Absyn.Equation eq;
8981 list<Absyn.EquationItem> xs;
8982
8983 case (((eqItem as Absyn.EQUATIONITEM(equation_ = eq as Absyn.EQ_NORETCALL(functionName = Absyn.CREF_IDENT(name = "transition")))) :: xs),transitions)
8984 algorithm
8985 14 transition := getTransitionInEquation(eq);
8986 14 transition := List.insert(transition, listLength(transition) + 1, getAnnotationInEquation(eqItem));
8987 transitions := listAppend({transition}, transitions);
8988 14 then
8989 getTransitionsInEquations(xs, transitions);
8990
8991 case ((_ :: xs), _)
8992 8 then
8993 getTransitionsInEquations(xs, inTransitions);
8994
8995 case ({}, _)
8996 then
8997 inTransitions;
8998
8999 end match;
9000 end getTransitionsInEquations;
9001
9002 protected function getTransitionInEquation
9003 "Transition is a Absyn.EQ_NORETCALL.
9004 So we read the function arguments and named arguments.
9005 This function should always return a list with 7 values."
9006 input Absyn.Equation inEquation;
9007 output list<String> outTransition;
9008 algorithm
9009 outTransition := match inEquation
9010 local
9011 list<Absyn.Exp> expArgs;
9012 list<Absyn.NamedArg> namedArgs;
9013 list<String> transition;
9014
9015 case Absyn.EQ_NORETCALL(functionArgs = Absyn.FUNCTIONARGS(args = expArgs, argNames = namedArgs))
9016 algorithm
9017 14 transition := List.map(expArgs, Dump.printExpStr);
9018 // if we have named args then give them preference
9019 14 transition := Interactive.addOrUpdateNamedArg(namedArgs, "immediate", "true", transition, 4);
9020 14 transition := Interactive.addOrUpdateNamedArg(namedArgs, "reset", "true", transition, 5);
9021 14 transition := Interactive.addOrUpdateNamedArg(namedArgs, "synchronize", "false", transition, 6);
9022 14 transition := Interactive.addOrUpdateNamedArg(namedArgs, "priority", "1", transition, 7);
9023 then
9024 transition;
9025
9026 else {"", "", "", "true", "true", "false", "1"};
9027
9028 end match;
9029 end getTransitionInEquation;
9030
9031 protected function getInitialStates
9032 input Absyn.Path path;
9033 input Absyn.Program p;
9034 output Values.Value res;
9035 protected
9036 list<list<String>> initialStates;
9037 Absyn.Class cdef;
9038 algorithm
9039 1 cdef := ProgramUtil.getPathedClassInProgram(path, p);
9040 1 initialStates := listReverse(getInitialStatesInClass(cdef));
9041 1 res := ValuesMake.makeArray(List.map(initialStates, ValuesMake.makeStringArray));
9042 end getInitialStates;
9043
9044 protected function getInitialStatesInClass
9045 "Gets the list of initial states in a class."
9046 input Absyn.Class inClass;
9047 output list<list<String>> outInitialStates;
9048 algorithm
9049 outInitialStates := match inClass
9050 local
9051 list<list<String>> initialStates;
9052 list<Absyn.ClassPart> parts;
9053
9054 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
9055 algorithm
9056 1 initialStates := getInitialStatesInClassParts(parts);
9057 then
9058 initialStates;
9059
9060 // handle also the case model extends X end X;
9061 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
9062 algorithm
9063 ✗ initialStates := getInitialStatesInClassParts(parts);
9064 then
9065 initialStates;
9066
9067 case Absyn.CLASS(body = Absyn.DERIVED()) then {};
9068
9069 end match;
9070 end getInitialStatesInClass;
9071
9072 protected function getInitialStatesInClassParts
9073 "Helper function for getInitialStatesInClass."
9074 input list<Absyn.ClassPart> inAbsynClassPartLst;
9075 output list<list<String>> outInitialStates;
9076 algorithm
9077 outInitialStates := matchcontinue inAbsynClassPartLst
9078 local
9079 list<list<String>> initialStates1, initialStates2;
9080 list<Absyn.EquationItem> eqlist;
9081 list<Absyn.ClassPart> xs;
9082
9083 case Absyn.EQUATIONS(contents = eqlist) :: xs
9084 algorithm
9085 1 initialStates1 := getInitialStatesInEquations(eqlist, {});
9086 1 initialStates2 := getInitialStatesInClassParts(xs);
9087 1 then
9088 listAppend(initialStates1, initialStates2);
9089
9090 case _ :: xs
9091 algorithm
9092 1 initialStates1 := getInitialStatesInClassParts(xs);
9093 then
9094 initialStates1;
9095
9096 case {}
9097 then {};
9098
9099 end matchcontinue;
9100 end getInitialStatesInClassParts;
9101
9102 protected function getInitialStatesInEquations
9103 "Helper function for getInitialStatesInClass."
9104 input list<Absyn.EquationItem> inAbsynEquationItemLst;
9105 input list<list<String>> inInitialStates;
9106 output list<list<String>> outInitialStates;
9107 algorithm
9108 outInitialStates := match (inAbsynEquationItemLst, inInitialStates)
9109 local
9110 list<list<String>> initialStates;
9111 list<String> initialState;
9112 Absyn.EquationItem eqItem;
9113 Absyn.Equation eq;
9114 list<Absyn.EquationItem> xs;
9115
9116 case (((eqItem as Absyn.EQUATIONITEM(equation_ = eq as Absyn.EQ_NORETCALL(functionName = Absyn.CREF_IDENT(name = "initialState")))) :: xs),initialStates)
9117 algorithm
9118 1 initialState := getInitialStateInEquation(eq);
9119 1 initialState := List.insert(initialState, listLength(initialState) + 1, getAnnotationInEquation(eqItem));
9120 initialStates := listAppend({initialState}, initialStates);
9121 1 then
9122 getInitialStatesInEquations(xs, initialStates);
9123
9124 case ((_ :: xs), _)
9125 4 then
9126 getInitialStatesInEquations(xs, inInitialStates);
9127
9128 case ({}, _)
9129 then
9130 inInitialStates;
9131
9132 end match;
9133 end getInitialStatesInEquations;
9134
9135 protected function getInitialStateInEquation
9136 "Initial state is a Absyn.EQ_NORETCALL.
9137 So we read the function arguments and named arguments.
9138 This function should always return a list with 1 value."
9139 input Absyn.Equation inEquation;
9140 output list<String> outInitialState;
9141 algorithm
9142 outInitialState := match inEquation
9143 local
9144 list<Absyn.Exp> expArgs;
9145 list<String> initialState;
9146
9147 case Absyn.EQ_NORETCALL(functionArgs = Absyn.FUNCTIONARGS(args = expArgs))
9148 algorithm
9149 1 initialState := List.map(expArgs, Dump.printExpStr);
9150 then
9151 initialState;
9152
9153 else {""};
9154
9155 end match;
9156 end getInitialStateInEquation;
9157
9158 protected function addInitialState
9159 "Adds an initial state to the model, i.e., initialState(state1)"
9160 input Absyn.Path inPath;
9161 input String state;
9162 input list<Absyn.NamedArg> inAbsynNamedArgLst;
9163 input Absyn.Program inProgram;
9164 output Boolean b;
9165 output Absyn.Program outProgram;
9166 algorithm
9167 2 (b, outProgram) := addInitialStateWithAnnotation(inPath, state, InteractiveUtil.annotationListToAbsyn(inAbsynNamedArgLst), inProgram);
9168 end addInitialState;
9169
9170 protected function addInitialStateWithAnnotation
9171 "Adds an initial state to the model, i.e., initialState(state1)"
9172 input Absyn.Path inPath;
9173 input String state;
9174 input Absyn.Annotation inAnnotation;
9175 input Absyn.Program inProgram;
9176 output Boolean b;
9177 output Absyn.Program outProgram = inProgram;
9178 protected
9179 Absyn.Path package_;
9180 Absyn.Class cdef, newcdef;
9181 Option<Absyn.Comment> cmt;
9182 algorithm
9183 try
9184 2 cdef := ProgramUtil.getPathedClassInProgram(inPath, inProgram);
9185 2 cmt := SOME(Absyn.COMMENT(SOME(inAnnotation), NONE()));
9186 4 newcdef := InteractiveUtil.addToEquation(cdef, Absyn.EQUATIONITEM(Absyn.EQ_NORETCALL(Absyn.CREF_IDENT("initialState", {}),
9187 Absyn.FUNCTIONARGS({Absyn.CREF(Absyn.CREF_IDENT(state, {}))}, {})), cmt, Absyn.dummyInfo));
9188
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if AbsynUtil.pathIsIdent(AbsynUtil.makeNotFullyQualified(inPath)) then
9189 2 outProgram := ProgramUtil.updateProgram(Absyn.PROGRAM({newcdef},inProgram.within_), inProgram);
9190 else
9191 ✗ package_ := AbsynUtil.stripLast(inPath);
9192 ✗ outProgram := ProgramUtil.updateProgram(Absyn.PROGRAM({newcdef},Absyn.WITHIN(package_)), inProgram);
9193 end if;
9194 b := true;
9195 else
9196 b := false;
9197 end try;
9198 end addInitialStateWithAnnotation;
9199
9200 protected function deleteInitialState
9201 "Delete the initial state initialState(c1) from a model."
9202 input Absyn.Path inPath;
9203 input String state;
9204 input Absyn.Program inProgram;
9205 output Boolean b;
9206 output Absyn.Program outProgram;
9207 algorithm
9208 (b,outProgram) := matchcontinue (inPath, state, inProgram)
9209 local
9210 Absyn.Path modelpath, modelwithin;
9211 Absyn.Class cdef, newcdef;
9212 Absyn.Program newp, p;
9213 String state_;
9214
9215 case (modelpath, state_, (p as Absyn.PROGRAM()))
9216 algorithm
9217 2 cdef := ProgramUtil.getPathedClassInProgram(modelpath, p);
9218 2 newcdef := deleteInitialStateInClass(cdef, state_);
9219
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if AbsynUtil.pathIsIdent(AbsynUtil.makeNotFullyQualified(modelpath)) then
9220 2 newp := ProgramUtil.updateProgram(Absyn.PROGRAM({newcdef}, Absyn.TOP()), p);
9221 else
9222 ✗ modelwithin := AbsynUtil.stripLast(modelpath);
9223 ✗ newp := ProgramUtil.updateProgram(Absyn.PROGRAM({newcdef}, Absyn.WITHIN(modelwithin)), p);
9224 end if;
9225 then
9226 (true, newp);
9227 case (_,_,(p as Absyn.PROGRAM())) then (false, p);
9228 end matchcontinue;
9229 end deleteInitialState;
9230
9231 protected function deleteInitialStateInClass
9232 "Helper function to deleteInitialState."
9233 input Absyn.Class inClass;
9234 input String state;
9235 output Absyn.Class outClass;
9236 algorithm
9237 outClass := match inClass
9238 local
9239 list<Absyn.EquationItem> eqlst,eqlst_1;
9240 list<Absyn.ClassPart> parts2,parts;
9241 String bcname;
9242 Option<String> cmt;
9243 list<Absyn.ElementArg> modif;
9244 list<String> typeVars;
9245 list<Absyn.NamedArg> classAttrs;
9246 list<Absyn.Annotation> ann;
9247 /* a class with parts */
9248 case outClass as Absyn.CLASS(
9249 body = Absyn.PARTS(typeVars = typeVars,classAttrs = classAttrs,classParts = parts,ann=ann,comment = cmt))
9250 algorithm
9251 2 eqlst := InteractiveUtil.getEquationList(parts);
9252 2 eqlst_1 := deleteInitialStateInEqlist(eqlst, state);
9253 2 parts2 := InteractiveUtil.replaceEquationList(parts, eqlst_1);
9254 4 outClass.body := Absyn.PARTS(typeVars,classAttrs,parts2,ann,cmt);
9255 then outClass;
9256 /* an extended class with parts: model extends M end M; */
9257 case outClass as Absyn.CLASS(
9258 body = Absyn.CLASS_EXTENDS(baseClassName = bcname,modifications=modif,parts = parts,ann = ann,comment = cmt))
9259 algorithm
9260 ✗ eqlst := InteractiveUtil.getEquationList(parts);
9261 ✗ eqlst_1 := deleteInitialStateInEqlist(eqlst, state);
9262 ✗ parts2 := InteractiveUtil.replaceEquationList(parts, eqlst_1);
9263 ✗ outClass.body := Absyn.CLASS_EXTENDS(bcname,modif,cmt,parts2,ann);
9264 then outClass;
9265 end match;
9266 end deleteInitialStateInClass;
9267
9268 protected function deleteInitialStateInEqlist
9269 "Helper function to deleteInitialState."
9270 input list<Absyn.EquationItem> inEqs;
9271 input String state;
9272 output list<Absyn.EquationItem> outEqs;
9273 protected
9274 function is_matching_initial_state
9275 input Absyn.EquationItem item;
9276 input String state;
9277 output Boolean isMatch;
9278 protected
9279 Absyn.ComponentRef name;
9280 list<Absyn.Exp> args;
9281 algorithm
9282 isMatch := match item
9283 case Absyn.EQUATIONITEM(equation_ = Absyn.EQ_NORETCALL(functionName = name, functionArgs = Absyn.FUNCTIONARGS(args = args)))
9284 guard AbsynUtil.crefEqual(name, Absyn.CREF_IDENT("initialState", {}))
9285
4/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 2 times.
4 then not listEmpty(args) and state == Dump.printExpStr(listHead(args));
9286 else false;
9287 end match;
9288 end is_matching_initial_state;
9289 algorithm
9290
6/6
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 2 times.
14 outEqs := list(e for e guard not is_matching_initial_state(e, state) in inEqs);
9291 end deleteInitialStateInEqlist;
9292
9293 function getComponentInfo
9294 input Absyn.Element comp;
9295 input Interactive.GraphicEnvCache inEnv;
9296 input Boolean isProtected;
9297 output list<Values.Value> vs;
9298 algorithm
9299 vs := match comp
9300 local
9301 Absyn.Path p_1, p;
9302 String typename, inout_str, variability_str, dir_str, name, comment;
9303 Boolean r_1;
9304 Absyn.ElementAttributes attr;
9305 list<String> dims, dims1;
9306 Absyn.ArrayDim subs;
9307 Absyn.ElementSpec spec;
9308
9309 case Absyn.ELEMENT(specification = spec as Absyn.COMPONENTS(attributes = attr,typeSpec = Absyn.TPATH(p, _)))
9310 algorithm
9311 typename := matchcontinue ()
9312 case ()
9313 algorithm
9314 6 (_, p_1) := Interactive.mkFullyQual(inEnv, p);
9315 6 then AbsynUtil.pathString(p_1);
9316 ✗ else AbsynUtil.pathString(p);
9317 end matchcontinue;
9318 vs := {};
9319
9320
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 dims1 := list(Dump.printSubscriptStr(sub) for sub in attr.arrayDim);
9321 6 r_1 := Interactive.keywordReplaceable(comp.redeclareKeywords);
9322 6 inout_str := AbsynUtil.innerOuterStr(comp.innerOuter);
9323 6 variability_str := attrVariabilityStr(attr);
9324 6 dir_str := attrDirectionStr(attr);
9325
9326
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for ci in spec.components loop
9327 6 (name, comment) := getComponentitemsName(ci);
9328
9329 6 Absyn.COMPONENTITEM(component=Absyn.COMPONENT(arrayDim=subs)) := ci;
9330
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 dims := listAppend(list(Dump.printSubscriptStr(sub) for sub in subs), dims1);
9331
9332 6 vs := makeGetComponentsRecord(
9333 className = typename, name = name, comment = comment,
9334 isProtected=isProtected, isReplaceable=r_1, isFinal=comp.finalPrefix, innerOuter=inout_str, isFlow=attr.flowPrefix,
9335 isStream=attr.streamPrefix, variability=variability_str, inputOutput=dir_str, dimensions=dims) :: vs;
9336 end for;
9337 then vs;
9338 end match;
9339 end getComponentInfo;
9340
9341 function makeGetComponentsRecord
9342 input String className;
9343 input String name;
9344 input String comment;
9345 input Boolean isProtected;
9346 input Boolean isFinal;
9347 input Boolean isFlow;
9348 input Boolean isStream;
9349 input Boolean isReplaceable;
9350 input String variability;
9351 input String innerOuter;
9352 input String inputOutput;
9353 input list<String> dimensions;
9354 output Values.Value v;
9355 algorithm
9356
7/14
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 6 times.
✗ Branch 16 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 6 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 6 times.
42 v := Values.RECORD(
9357 Absyn.QUALIFIED("OpenModelica", Absyn.QUALIFIED("Scripting", Absyn.QUALIFIED("getComponentsTest", Absyn.IDENT("Component")))),
9358 {
9359 Values.STRING(className),
9360 Values.STRING(name),
9361 Values.STRING(comment),
9362 Values.BOOL(isProtected),
9363 Values.BOOL(isFinal),
9364 Values.BOOL(isFlow),
9365 Values.BOOL(isStream),
9366 Values.BOOL(isReplaceable),
9367 Values.STRING(variability),
9368 Values.STRING(innerOuter),
9369 Values.STRING(inputOutput),
9370 ValuesMake.makeArray(list(Values.STRING(s) for s in dimensions))
9371 },
9372 {"className","name","comment","isProtected","isFinal","isFlow","isStream","isReplaceable","variability","innerOuter","inputOutput","dimensions"},
9373 -1
9374 );
9375 end makeGetComponentsRecord;
9376
9377 function attrVariabilityStr
9378 "Helper function to get_component_info,
9379 retrieve variability as a string."
9380 input Absyn.ElementAttributes inElementAttributes;
9381 output String outString;
9382 algorithm
9383 outString:=
9384 match inElementAttributes
9385 case Absyn.ATTR(variability = Absyn.VAR()) then "";
9386 case Absyn.ATTR(variability = Absyn.DISCRETE()) then "discrete";
9387 case Absyn.ATTR(variability = Absyn.PARAM()) then "parameter";
9388 case Absyn.ATTR(variability = Absyn.CONST()) then "constant";
9389 end match;
9390 end attrVariabilityStr;
9391
9392 function attrDirectionStr
9393 "Helper function to get_component_info,
9394 retrieve direction as a string."
9395 input Absyn.ElementAttributes inElementAttributes;
9396 output String outString;
9397 algorithm
9398 outString:=
9399 match inElementAttributes
9400 case Absyn.ATTR(direction = Absyn.INPUT()) then "input";
9401 case Absyn.ATTR(direction = Absyn.OUTPUT()) then "output";
9402 case Absyn.ATTR(direction = Absyn.BIDIR()) then "";
9403 end match;
9404 end attrDirectionStr;
9405
9406 function getComponentitemsName
9407 " separated list of all component names and comments (if any)."
9408 input Absyn.ComponentItem ci;
9409 output String name;
9410 output String comment;
9411 algorithm
9412 (name, comment) := match ci
9413 local
9414 String c1,s2;
9415 case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = c1),comment = SOME(Absyn.COMMENT(_,SOME(s2))))
9416 then (c1, s2);
9417 case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = c1),comment = SOME(Absyn.COMMENT(_,_)))
9418 then (c1, "");
9419 case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = c1),comment = NONE())
9420 then (c1, "");
9421 end match;
9422 end getComponentitemsName;
9423
9424 function getModelFigures
9425 "The figures sub-annotation of Documentation, as Scripting.Figure records."
9426 input Absyn.Path classPath;
9427 input Absyn.Program program;
9428 output Values.Value result;
9429 protected
9430 Absyn.Class cls;
9431 Option<list<Values.Value>> ofigs;
9432 list<Values.Value> figs;
9433 algorithm
9434 ✗ cls := ProgramUtil.getPathedClassInProgram(classPath, program);
9435 ✗ ofigs := AbsynUtil.getNamedAnnotationInClass(cls,
9436 Absyn.QUALIFIED("Documentation", Absyn.IDENT("figures")), figuresFromMod);
9437 figs := match ofigs case SOME(figs) then figs; else {}; end match;
9438 ✗ result := ValuesMake.makeArray(figs);
9439 end getModelFigures;
9440
9441 function figuresFromMod
9442 input Option<Absyn.Modification> mod;
9443 output list<Values.Value> figures;
9444 algorithm
9445 figures := match mod
9446 local
9447 Absyn.Exp exp;
9448 case SOME(Absyn.CLASSMOD(eqMod = Absyn.EQMOD(exp = exp)))
9449 ✗ then list(figureValue(e) for e in figureExpElements(exp));
9450 else {};
9451 end match;
9452 end figuresFromMod;
9453
9454 function figureExpElements
9455 "Array elements of a figures/plots/curves value, or the value itself if scalar."
9456 input Absyn.Exp exp;
9457 output list<Absyn.Exp> exps;
9458 algorithm
9459 exps := match exp
9460 ✗ case Absyn.ARRAY() then exp.arrayExp;
9461 else {exp};
9462 end match;
9463 end figureExpElements;
9464
9465 function figureValue
9466 input Absyn.Exp exp;
9467 output Values.Value value;
9468 protected
9469 list<tuple<String, Absyn.Exp>> args;
9470 list<Values.Value> plots;
9471 algorithm
9472 ✗ args := figureArgs(exp, {"title", "identifier", "group", "preferred", "plots", "caption"});
9473 plots := match figureArgExp(args, "plots")
9474 local Absyn.Exp e;
9475 ✗ case SOME(e) then list(plotValue(p) for p in figureExpElements(e));
9476 else {};
9477 end match;
9478 ✗ value := Values.RECORD(Absyn.IDENT("OpenModelica.Scripting.Figure"),
9479 {figureStringArg(args, "title", ""),
9480 figureStringArg(args, "identifier", ""),
9481 figureStringArg(args, "group", ""),
9482 figureBoolArg(args, "preferred", false),
9483 ValuesMake.makeArray(plots),
9484 figureStringArg(args, "caption", "")},
9485 {"title", "identifier", "group", "preferred", "plots", "caption"}, -1);
9486 end figureValue;
9487
9488 function plotValue
9489 input Absyn.Exp exp;
9490 output Values.Value value;
9491 protected
9492 list<tuple<String, Absyn.Exp>> args;
9493 list<Values.Value> curves;
9494 algorithm
9495 ✗ args := figureArgs(exp, {"title", "identifier", "curves", "x", "y"});
9496 curves := match figureArgExp(args, "curves")
9497 local Absyn.Exp e;
9498 ✗ case SOME(e) then list(curveValue(c) for c in figureExpElements(e));
9499 else {};
9500 end match;
9501 ✗ value := Values.RECORD(Absyn.IDENT("OpenModelica.Scripting.Plot"),
9502 {figureStringArg(args, "title", ""),
9503 figureStringArg(args, "identifier", ""),
9504 ValuesMake.makeArray(curves),
9505 axisValue(figureArgExp(args, "x")),
9506 axisValue(figureArgExp(args, "y"))},
9507 {"title", "identifier", "curves", "x", "y"}, -1);
9508 end plotValue;
9509
9510 function curveValue
9511 input Absyn.Exp exp;
9512 output Values.Value value;
9513 protected
9514 list<tuple<String, Absyn.Exp>> args;
9515 algorithm
9516 ✗ args := figureArgs(exp, {"x", "y", "legend", "zOrder"});
9517 ✗ value := Values.RECORD(Absyn.IDENT("OpenModelica.Scripting.Curve"),
9518 {figureRefArg(args, "x", "time"),
9519 figureRefArg(args, "y", ""),
9520 figureStringArg(args, "legend", ""),
9521 figureIntArg2(args, "zOrder", 0)},
9522 {"x", "y", "legend", "zOrder"}, -1);
9523 end curveValue;
9524
9525 function axisValue
9526 input Option<Absyn.Exp> oexp;
9527 output Values.Value value;
9528 protected
9529 list<tuple<String, Absyn.Exp>> args;
9530 algorithm
9531 ✗ args := match oexp case SOME(_) then figureArgs(Util.getOption(oexp), {"min", "max", "unit", "label", "scale"}); else {}; end match;
9532 ✗ value := Values.RECORD(Absyn.IDENT("OpenModelica.Scripting.Axis"),
9533 {figureRealBoundArg(args, "min"),
9534 figureRealBoundArg(args, "max"),
9535 figureStringArg(args, "unit", ""),
9536 figureStringArg(args, "label", ""),
9537 axisScaleValue(figureArgExp(args, "scale"))},
9538 {"min", "max", "unit", "label", "scale"}, -1);
9539 end axisValue;
9540
9541 function axisScaleValue
9542 input Option<Absyn.Exp> oexp;
9543 output Values.Value value;
9544 protected
9545 String scaleType = "Linear";
9546 Integer base = 10;
9547 algorithm
9548 _ := match oexp
9549 local
9550 Absyn.ComponentRef cr;
9551 Absyn.FunctionArgs fargs;
9552 case SOME(Absyn.CALL(function_ = cr, functionArgs = fargs))
9553 algorithm
9554 ✗ scaleType := AbsynUtil.crefIdent(cr);
9555 ✗ base := figureIntArg(figureArgs(Absyn.CALL(cr, fargs, {}), {"base"}), "base", 10);
9556 then ();
9557 else ();
9558 end match;
9559 ✗ value := Values.RECORD(Absyn.IDENT("OpenModelica.Scripting.AxisScale"),
9560 {Values.STRING(scaleType), Values.INTEGER(base)},
9561 {"scaleType", "base"}, -1);
9562 end axisScaleValue;
9563
9564 function figureArgs
9565 "Maps a record-constructor call's arguments to (fieldName, exp) pairs;
9566 positional args by declared field order, named args by name."
9567 input Absyn.Exp exp;
9568 input list<String> fieldNames;
9569 output list<tuple<String, Absyn.Exp>> args = {};
9570 protected
9571 list<Absyn.Exp> pos;
9572 list<Absyn.NamedArg> named;
9573 list<String> names = fieldNames;
9574 String name;
9575 algorithm
9576 () := match exp
9577 case Absyn.CALL(functionArgs = Absyn.FUNCTIONARGS(args = pos, argNames = named))
9578 algorithm
9579 ✗ for e in pos loop
9580 ✗ name :: names := names;
9581 ✗ args := (name, e) :: args;
9582 end for;
9583 ✗ for na in named loop
9584 ✗ args := (na.argName, na.argValue) :: args;
9585 end for;
9586 then ();
9587 else ();
9588 end match;
9589 end figureArgs;
9590
9591 function figureArgExp
9592 input list<tuple<String, Absyn.Exp>> args;
9593 input String name;
9594 output Option<Absyn.Exp> oexp = NONE();
9595 protected
9596 String n;
9597 Absyn.Exp e;
9598 algorithm
9599 ✗ for a in args loop
9600 ✗ (n, e) := a;
9601 ✗ if n == name then
9602 oexp := SOME(e);
9603 ✗ return;
9604 end if;
9605 end for;
9606 end figureArgExp;
9607
9608 function figureStringArg
9609 input list<tuple<String, Absyn.Exp>> args;
9610 input String name;
9611 input String default;
9612 output Values.Value value;
9613 algorithm
9614 value := match figureArgExp(args, name)
9615 ✗ case SOME(Absyn.STRING()) then Values.STRING(figureArgString(args, name, default));
9616 ✗ else Values.STRING(default);
9617 end match;
9618 end figureStringArg;
9619
9620 function figureArgString
9621 input list<tuple<String, Absyn.Exp>> args;
9622 input String name;
9623 input String default;
9624 output String value;
9625 algorithm
9626 value := match figureArgExp(args, name)
9627 local String s;
9628 case SOME(Absyn.STRING(value = s)) then s;
9629 else default;
9630 end match;
9631 end figureArgString;
9632
9633 function figureRefArg
9634 "A Curve x/y result reference, serialized as its Modelica source text."
9635 input list<tuple<String, Absyn.Exp>> args;
9636 input String name;
9637 input String default;
9638 output Values.Value value;
9639 algorithm
9640 value := match figureArgExp(args, name)
9641 local Absyn.Exp e;
9642 ✗ case SOME(e) then Values.STRING(Dump.printExpStr(e));
9643 ✗ else Values.STRING(default);
9644 end match;
9645 end figureRefArg;
9646
9647 function figureBoolArg
9648 input list<tuple<String, Absyn.Exp>> args;
9649 input String name;
9650 input Boolean default;
9651 output Values.Value value;
9652 algorithm
9653 value := match figureArgExp(args, name)
9654 local Boolean b;
9655 ✗ case SOME(Absyn.BOOL(value = b)) then Values.BOOL(b);
9656 ✗ else Values.BOOL(default);
9657 end match;
9658 end figureBoolArg;
9659
9660 function figureIntArg
9661 input list<tuple<String, Absyn.Exp>> args;
9662 input String name;
9663 input Integer default;
9664 output Integer value;
9665 algorithm
9666 value := match figureArgExp(args, name)
9667 local Integer i;
9668 case SOME(Absyn.INTEGER(value = i)) then i;
9669 else default;
9670 end match;
9671 end figureIntArg;
9672
9673 function figureRealBoundArg
9674 "An axis bound: empty Real[:] when absent (auto), length 1 when given."
9675 input list<tuple<String, Absyn.Exp>> args;
9676 input String name;
9677 output Values.Value value;
9678 algorithm
9679 value := match figureArgExp(args, name)
9680 local Absyn.Exp e;
9681 ✗ case SOME(e) then ValuesMake.makeArray({Values.REAL(figureExpReal(e))});
9682 ✗ else ValuesMake.makeArray({});
9683 end match;
9684 end figureRealBoundArg;
9685
9686 function figureExpReal
9687 input Absyn.Exp exp;
9688 output Real value;
9689 algorithm
9690 value := match exp
9691 local Integer i; String s;
9692 ✗ case Absyn.INTEGER(value = i) then intReal(i);
9693 ✗ case Absyn.REAL(value = s) then stringReal(s);
9694 ✗ case Absyn.UNARY(op = Absyn.UMINUS()) then -figureExpReal(exp.exp);
9695 else 0.0;
9696 end match;
9697 end figureExpReal;
9698
9699 function figureIntArg2
9700 input list<tuple<String, Absyn.Exp>> args;
9701 input String name;
9702 input Integer default;
9703 output Values.Value value;
9704 algorithm
9705 ✗ value := Values.INTEGER(figureIntArg(args, name, default));
9706 end figureIntArg2;
9707
9708 function getAnnotationNamedModifiers
9709 input Absyn.Path classPath;
9710 input String annotationName;
9711 input Absyn.Program program;
9712 output Values.Value result;
9713 protected
9714 Absyn.Class cls;
9715 list<String> names;
9716
9717 function get_names
9718 input Option<Absyn.Modification> mod;
9719 output list<String> names;
9720 protected
9721 Absyn.Modification m;
9722 list<Absyn.Path> paths;
9723 algorithm
9724 names := match mod
9725 case SOME(m)
9726 algorithm
9727
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
6 paths := list(AbsynUtil.elementArgName(a) for a in m.elementArgLst);
9728
5/6
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 2 times.
6 then
9729 list(AbsynUtil.pathString(p) for p guard AbsynUtil.pathIsIdent(p) in paths);
9730 else {};
9731 end match;
9732 end get_names;
9733 algorithm
9734 2 cls := ProgramUtil.getPathedClassInProgram(classPath, program);
9735
2/4
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 SOME(names) := AbsynUtil.getNamedAnnotationInClass(cls, Absyn.Path.IDENT(annotationName), get_names);
9736 2 result := ValuesMake.makeStringArray(names);
9737 end getAnnotationNamedModifiers;
9738
9739 function getOptModifierValue
9740 input Option<Absyn.Modification> modifier;
9741 output Values.Value value;
9742 protected
9743 Absyn.Modification mod;
9744 Absyn.Exp exp;
9745 algorithm
9746
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 SOME(mod) := modifier;
9747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 Absyn.EqMod.EQMOD(exp = exp) := mod.eqMod;
9748 4 value := ValuesUtil.absynExpValue(exp);
9749 end getOptModifierValue;
9750
9751 function getAnnotationModifierValue
9752 input Absyn.Path classPath;
9753 input String annotationName;
9754 input String modifierName;
9755 input Absyn.Program program;
9756 output Values.Value result;
9757 protected
9758 Absyn.Class cls;
9759 algorithm
9760 4 cls := ProgramUtil.getPathedClassInProgram(classPath, program);
9761
2/4
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
4 SOME(result) := AbsynUtil.getNamedAnnotationInClass(cls,
9762 Absyn.Path.QUALIFIED(annotationName, Absyn.Path.IDENT(modifierName)), getOptModifierValue);
9763 end getAnnotationModifierValue;
9764
9765 function makeLoadLibrariesEntryAbsyn "Needed to be able to resolve modelica:// during runtime, etc.
9766 Should not be part of CevalScript since ModelicaServices needs this feature and the frontend needs to take care of it."
9767 input Absyn.Class cl;
9768 input list<Values.Value> acc;
9769 output list<Values.Value> out;
9770 algorithm
9771 out := match cl
9772 local
9773 String name,fileName,dir;
9774 Values.Value v;
9775 Boolean b;
9776 case Absyn.CLASS(info=SOURCEINFO(fileName="<interactive>")) then acc;
9777 case Absyn.CLASS(name=name,info=SOURCEINFO(fileName=fileName))
9778 algorithm
9779 ✗ dir := System.dirname(fileName);
9780 ✗ fileName := System.basename(fileName);
9781 ✗ v := ValuesMake.makeArray({Values.STRING(name),Values.STRING(dir)});
9782 ✗ b := stringEq(fileName,"ModelicaBuiltin.mo") or stringEq(fileName,"MetaModelicaBuiltin.mo") or stringEq(dir,".");
9783 ✗ then List.consOnTrue(not b,v,acc);
9784 end match;
9785 end makeLoadLibrariesEntryAbsyn;
9786
9787 function selectResultFile
9788 input output String resultFile;
9789 input String simflags;
9790 protected
9791 Integer nm;
9792 String f = "";
9793 algorithm
9794 // if there is no -r in the simflags, return
9795
2/2
✓ Branch 1 taken 1106 times.
✓ Branch 2 taken 42 times.
1148 if System.stringFind(simflags, "-r") < 0 then
9796 1106 return;
9797 end if;
9798 // never fail!
9799 try
9800 // match -r="file"
9801
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 42 times.
42 (nm, {_, f}) := System.regex(simflags, "-r=\"(.*?)\"", 2, true);
9802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if nm == 2 then
9803 42 resultFile := f; return;
9804 end if;
9805 // match -r='file'
9806
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 42 times.
42 (nm, {_, f}) := System.regex(simflags, "-r=\'(.*?)\'", 2, true);
9807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if nm == 2 then
9808 ✗ resultFile := f; return;
9809 end if;
9810 // match -r 'file'
9811
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 42 times.
42 (nm, {_, f}) := System.regex(simflags, "-r[ ]*\"(.*?)\"", 2, true);
9812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if nm == 2 then
9813 ✗ resultFile := f; return;
9814 end if;
9815 // match -r "file"
9816
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 42 times.
42 (nm, {_, f}) := System.regex(simflags, "-r[ ]*\'(.*?)\'", 2, true);
9817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if nm == 2 then
9818 ✗ resultFile := f; return;
9819 end if;
9820 // match -r=file
9821
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 42 times.
42 (nm, {_, f}) := System.regex(simflags, "-r=([^ ]*)", 2, true);
9822
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 28 times.
42 if nm == 2 then
9823 14 resultFile := f; return;
9824 end if;
9825 // match -r file
9826
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 28 times.
28 (nm, {_, f}) := System.regex(simflags, "-r[ ]*([^ ]*)", 2, true);
9827
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if nm == 2 then
9828 28 resultFile := f; return;
9829 end if;
9830 else
9831 // do nothing
9832 end try;
9833 end selectResultFile;
9834
9835 function instantiateModel
9836 input output FCore.Cache cache;
9837 input FCore.Graph env;
9838 input Absyn.Path path;
9839 output Values.Value result;
9840 protected
9841 String str;
9842 Option<DAE.DAElist> odae;
9843 Flags.Flag flags;
9844 algorithm
9845
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 102 times.
102 if isProtectedContentAccess(path) then
9846 // if AST contains encrypted class show nothing
9847 result := Values.STRING("");
9848 ✗ return;
9849 end if;
9850
9851 str := matchcontinue ()
9852 case ()
9853 algorithm
9854 102 ExecStat.execStatReset();
9855 102 flags := loadCommandLineOptionsFromModel(path);
9856
9857 try
9858
3/4
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 94 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
102 (cache, _, odae, str) := runFrontEnd(cache, env, path, relaxedFrontEnd = false,
9859 dumpFlat = Config.flatModelica() and not Config.silent());
9860 102 ExecStat.execStat("runFrontEnd");
9861
9862
5/6
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 95 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 82 times.
102 if not stringEmpty(str) then
9863 // str already contains flat model.
9864 elseif isNone(odae) then
9865 13 str := "";
9866 elseif Config.silent() then
9867 ✗ str := "model " + AbsynUtil.pathString(path) + "\n /* Silent mode */\nend" +
9868 AbsynUtil.pathString(path) + ";\n"; // Not the empty string, so we can
9869 else
9870 82 str := DAEDump.dumpStr(Util.getOption(odae), FCore.getFunctionTree(cache));
9871 82 ExecStat.execStat("DAEDump.dumpStr");
9872 end if;
9873
9874 102 FlagsUtil.saveFlags(flags);
9875 else
9876 ✗ FlagsUtil.saveFlags(flags);
9877 ✗ fail();
9878 end try;
9879 102 then
9880 str;
9881
9882 case ()
9883 algorithm
9884 ✗ false := Interactive.existClass(path, SymbolTable.getAbsyn());
9885 ✗ Error.addMessage(Error.LOOKUP_ERROR, {AbsynUtil.pathString(path), "<TOP>"});
9886 then
9887 "";
9888
9889 else
9890 algorithm
9891 ✗ if Error.getNumMessages() == 0 then
9892 ✗ str := "Instantiation of " + AbsynUtil.pathString(path) +
9893 " failed with no error message";
9894 ✗ Error.addMessage(Error.INTERNAL_ERROR, {str, "<TOP>"});
9895 end if;
9896 then
9897 "";
9898 end matchcontinue;
9899
9900 102 result := Values.STRING(str);
9901 end instantiateModel;
9902
9903 protected function getConnectionList
9904 "@author: rahulp
9905 Returns a list of all connect equations including those in loops"
9906 input Absyn.Path className;
9907 output Values.Value valList;
9908 protected
9909 SCode.Program sp, annotation_sp;
9910 list<list<String>> connList;
9911 algorithm
9912 2 annotation_sp := AbsynToSCode.translateAbsyn2SCode(InteractiveUtil.modelicaAnnotationProgram(Config.getAnnotationVersion()));
9913 2 (_, sp) := FBuiltin.getInitialFunctions();
9914 2 sp := listAppend(SymbolTable.getSCode(), sp);
9915 2 connList := NFInst.instClassForConnection(className, sp, annotation_sp);
9916
4/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 2 times.
11 valList := ValuesMake.makeArray(list(ValuesMake.makeArray(List.map(conn, ValuesMake.makeString)) for conn in connList));
9917 end getConnectionList;
9918
9919 protected function runConversionScript
9920 input Absyn.Path clsPath;
9921 input String scriptFile;
9922 output Values.Value res;
9923 protected
9924 Absyn.Program p;
9925 Absyn.Class cls;
9926 Absyn.Within wi;
9927 algorithm
9928 try
9929 9 p := SymbolTable.getAbsyn();
9930 9 cls := ProgramUtil.getPathedClassInProgram(clsPath, p, showError = true);
9931 //System.startTimer();
9932 9 cls := Conversion.convertPackage(cls, scriptFile);
9933 //System.stopTimer();
9934 //print("Conversion took " + String(System.getTimerIntervalTime()) + " seconds.\n");
9935 8 wi := ProgramUtil.buildWithin(clsPath);
9936 8 p := ProgramUtil.updateProgram(Absyn.PROGRAM({cls}, wi), p);
9937 8 SymbolTable.setAbsyn(p);
9938 res := Values.BOOL(true);
9939 else
9940 res := Values.BOOL(false);
9941 end try;
9942 end runConversionScript;
9943
9944 protected function convertPackageToLibrary
9945 input Absyn.Path clsPath;
9946 input Absyn.Path libPath;
9947 input String libVersion;
9948 output Values.Value res;
9949 protected
9950 Absyn.Program p, lib_program;
9951 Absyn.Class cls, lib_cls;
9952 Absyn.Within wi;
9953 Option<String> uses_version;
9954 SemanticVersion.Version lib_version, lib_version_used;
9955 list<tuple<String, Option<String>, Option<String>>> conversions;
9956 list<String> scripts;
9957 String lib_name;
9958 algorithm
9959 try
9960 // Get the Absyn for the class and check which version of the library it's using.
9961 2 p := SymbolTable.getAbsyn();
9962 2 cls := ProgramUtil.getPathedClassInProgram(clsPath, p, showError = true);
9963 2 uses_version := Interactive.getUsedVersion(cls, libPath);
9964
9965
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
2 if isSome(uses_version) then
9966 1 lib_version_used := SemanticVersion.parse(Util.getOption(uses_version), true);
9967 else
9968 3 Error.addMessage(Error.CONVERSION_MISSING_USES,
9969 {AbsynUtil.pathString(clsPath), AbsynUtil.pathString(libPath)});
9970 1 fail();
9971 end if;
9972
9973 1 lib_name := AbsynUtil.pathFirstIdent(libPath);
9974 1 lib_version := SemanticVersion.parse(CevalScript.getPackageVersion(libPath, p));
9975
9976 // Check if the wanted version of the library is already loaded, otherwise
9977 // we need to load it.
9978
1/2
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 if SemanticVersion.compare(lib_version, SemanticVersion.parse(libVersion)) <> 0 then
9979 // Try to set the language standard to the version needed to load the wanted library.
9980
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 if lib_name == "Modelica" then
9981 ✗ Config.setLanguageStandardFromMSL("Modelica " + libVersion, force = true);
9982 end if;
9983
9984 // Load the library that we want to convert the class to.
9985
1/2
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
2 (lib_program, true) := CevalScript.loadModel({(libPath, lib_name, {libVersion}, false)},
9986 Settings.getModelicaPath(Testsuite.isRunning()), p, true, true, false, true);
9987 1 SymbolTable.setAbsyn(lib_program);
9988 else
9989 lib_program := p;
9990 end if;
9991
9992 // Get the version of the library.
9993 1 lib_version := SemanticVersion.parse(CevalScript.getPackageVersion(libPath, lib_program));
9994
9995 // Try to find a sequence of conversion scripts that can be used to convert
9996 // the class to the desired library version.
9997 1 lib_cls := ProgramUtil.getPathedClassInProgram(libPath, lib_program, showError = true);
9998 1 conversions := Interactive.getConversionsInClass(lib_cls);
9999 1 scripts := findConversionPaths(conversions, lib_version, lib_version_used);
10000
10001
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if listEmpty(scripts) then
10002 ✗ Error.addMessage(Error.CONVERSION_NO_COMPATIBLE_SCRIPT_FOUND,
10003 {AbsynUtil.pathString(libPath),
10004 SemanticVersion.toString(lib_version_used),
10005 SemanticVersion.toString(lib_version)});
10006 ✗ fail();
10007 end if;
10008
10009 // Apply the conversion scripts.
10010
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for script in scripts loop
10011 1 script := uriToFilename(script);
10012 1 cls := Conversion.convertPackage(cls, script);
10013 end for;
10014
10015 // Update the uses-annotation in the class to refer to the new version of the library.
10016 1 cls := Interactive.updateUsedVersion(cls, libPath, SemanticVersion.toString(lib_version));
10017
10018 // Finally update the class in the global Absyn.
10019 1 wi := ProgramUtil.buildWithin(clsPath);
10020 1 lib_program := ProgramUtil.updateProgram(Absyn.PROGRAM({cls}, wi), lib_program);
10021 1 SymbolTable.setAbsyn(lib_program);
10022 res := Values.BOOL(true);
10023 else
10024 res := Values.BOOL(false);
10025 end try;
10026 end convertPackageToLibrary;
10027
10028 function findConversionPaths
10029 "Tries to find the shortest path for converting from one version to another
10030 and returns the list of conversion scripts for that path. Usually only one
10031 conversion is needed, but sometimes the conversion might need to be done in
10032 several steps (e.g. 2.0.0 => 2.3.5 => 2.4.0)."
10033 input list<tuple<String, Option<String>, Option<String>>> conversions;
10034 input SemanticVersion.Version libVersion;
10035 input SemanticVersion.Version libVersionUsed;
10036 input Integer depth = 0;
10037 output list<String> scripts = {};
10038 protected
10039 list<list<String>> paths = {};
10040 Integer path_len, path_min = 100;
10041 algorithm
10042 // Abort if we go too deep to avoid crashing on malicious conversion annotations.
10043
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if depth > 100 then
10044 ✗ return;
10045 end if;
10046
10047 // Find the possible path for each conversion to the version we're looking for.
10048
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
4 for c in conversions loop
10049 3 paths := findConversionPath(c, libVersion, libVersionUsed, conversions, depth) :: paths;
10050 end for;
10051
10052 // Return the shortest non-empty path.
10053
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
4 for p in paths loop
10054 3 path_len := listLength(p);
10055
10056
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
3 if path_len > 0 and path_len < path_min then
10057 scripts := p;
10058 path_min := path_len;
10059 end if;
10060 end for;
10061 end findConversionPaths;
10062
10063 function findConversionPath
10064 input tuple<String, Option<String>, Option<String>> conversion;
10065 input SemanticVersion.Version libVersion;
10066 input SemanticVersion.Version libVersionUsed;
10067 input list<tuple<String, Option<String>, Option<String>>> conversions;
10068 input Integer depth;
10069 output list<String> scripts = {};
10070 protected
10071 String from;
10072 Option<String> to;
10073 Option<String> script;
10074 SemanticVersion.Version from_version, to_version;
10075 algorithm
10076 3 (from, to, script) := conversion;
10077
10078
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if isNone(script) then
10079 ✗ return;
10080 end if;
10081
10082 3 from_version := SemanticVersion.parse(from, true);
10083
10084
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
3 if SemanticVersion.compare(libVersionUsed, from_version) == 0 then
10085
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 if isSome(to) then
10086 ✗ to_version := SemanticVersion.parse(Util.getOption(to), true);
10087
10088 ✗ if SemanticVersion.compare(libVersion, to_version) <> 0 then
10089 ✗ scripts := findConversionPaths(conversions, libVersion, to_version, depth + 1);
10090 end if;
10091 end if;
10092
10093 1 scripts := Util.getOption(script) :: scripts;
10094 end if;
10095 end findConversionPath;
10096
10097 public function loadCommandLineOptionsFromModel
10098 "Applies flags from the __OpenModelica_commandLineOptions annotation of a given class and returns the old flags."
10099 input Absyn.Path className;
10100 output Flags.Flag oldFlags;
10101 protected
10102 String opts;
10103 list<String> args;
10104 algorithm
10105
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2722 times.
2722 if Config.ignoreCommandLineOptionsAnnotation() then
10106 ✗ oldFlags := FlagsUtil.loadFlags();
10107 ✗ return;
10108 end if;
10109
10110 2722 loadProgram(className);
10111
10112 // read the __OpenModelica_commandLineOptions
10113
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2722 times.
2722 Absyn.STRING(opts) := ProgramUtil.getNamedAnnotationExp(className, SymbolTable.getAbsyn(),
10114 Absyn.IDENT("__OpenModelica_commandLineOptions"), SOME(Absyn.STRING("")), Interactive.getAnnotationExp);
10115
10116
2/2
✓ Branch 0 taken 616 times.
✓ Branch 1 taken 2106 times.
2722 if not stringEmpty(opts) then
10117 // backup the current flags and apply the flags from the annotation
10118 616 oldFlags := FlagsUtil.backupFlags();
10119 616 args := System.strtok(opts, " ");
10120 616 FlagsUtil.readArgs(args);
10121 else
10122 2106 oldFlags := FlagsUtil.loadFlags();
10123 end if;
10124 end loadCommandLineOptionsFromModel;
10125
10126 public function isProtectedContentAccess
10127 "Loads the given class, then checks if any encrypted classes are present.
10128 Note that this checks for encrypted classes everywhere, not just in the
10129 given class. The reason the class is loaded first is to make sure it's
10130 included in the check, otherwise it might be automatically loaded later and
10131 bypass the check."
10132 input Absyn.Path className;
10133 output Boolean restricted;
10134 algorithm
10135 190 loadProgram(className);
10136 190 restricted := Interactive.astContainsEncryptedClass(SymbolTable.getAbsyn());
10137
10138
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 if restricted then
10139 ✗ Error.addMessage(Error.ACCESS_ENCRYPTED_PROTECTED_CONTENTS, {});
10140 end if;
10141 end isProtectedContentAccess;
10142
10143 annotation(__OpenModelica_Interface="backend_main");
10144
10145 end CevalScriptBackend;
10146