Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 46.1% 454 / 0 / 984
Functions: -% 0 / 1 / 1
Branches: 40.2% 297 / 0 / 738

OMCompiler/Compiler/Script/CevalScript.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 CevalScript
37 " file: CevalScript.mo
38 package: CevalScript
39 description: Constant propagation of expressions
40
41
42 This module handles scripting.
43
44 Input:
45 Env: Environment with bindings
46 Exp: Expression to evaluate
47 Bool flag determines whether the current instantiation is implicit
48 InteractiveSymbolTable is optional, and used in interactive mode, e.g. from OMShell
49
50 Output:
51 Value: The evaluated value
52 InteractiveSymbolTable: Modified symbol table
53 Subscript list : Evaluates subscripts and generates constant expressions."
54
55 // public imports
56 import Absyn;
57 import ProgramUtil;
58 import AbsynUtil;
59 import Ceval;
60 import CevalScriptOMSimulator;
61 import DAE;
62 import ErrorTypes;
63 import FCore;
64 import Interactive;
65 import Interactive.Access;
66 import SimCode;
67 import Values;
68
69 // protected imports
70 protected
71 import Autoconf;
72 import BaseHashSet;
73 import Builtin;
74 import CevalFunction;
75 import CevalScriptBackend;
76 import ClassInf;
77 import ClassLoader;
78 import CodegenCFunctions;
79 import CodegenMidToC;
80 import CodegenWasmJitFunctions;
81 import ComponentReference;
82 import Config;
83 import DAEUtil;
84 import Debug;
85 import Dump;
86 import DynLoad;
87 import Error;
88 import ErrorExt;
89 import ExecStat.{execStat,execStatReset};
90 import Expression;
91 import FBuiltin;
92 import FGraph;
93 import Flags;
94 import FlagsUtil;
95 import FNode;
96 import GCExt;
97 import GenerateAPIFunctionsTpl;
98 import Global;
99 import Graph;
100 import HashSetString;
101 import Inst;
102 import InstHashTable;
103 import InstFunction;
104 import InteractiveUtil;
105 import List;
106 import Lookup;
107 import Mod;
108 import NFApi;
109 import PackageManagement;
110 import Parser;
111 import Print;
112 import SCode;
113 import SCodeDump;
114 import SCodeUtil;
115 import SemanticVersion;
116 import Settings;
117 import SimCodeFunction;
118 import SimCodeFunctionUtil;
119 import DAEToMid;
120 import MidCode;
121 import StackOverflow;
122 import Static;
123 import JSON;
124 import StringUtil;
125 import SymbolTable;
126 import System;
127 import Tpl;
128 import Types;
129 import UnorderedMap;
130 import Unparsing;
131 import Util;
132 import ValuesUtil;
133 import MetaModelica.Dangerous.listReverseInPlace;
134
135 public
136
137 function ceval "
138 This is a wrapper funtion to Ceval.ceval. The purpose of this
139 function is to concetrate all the calls to Ceval.ceval made from
140 the Script files. This will simplify the separation of the scripting
141 environment from the FrontEnd"
142 input FCore.Cache inCache;
143 input FCore.Graph inEnv;
144 input DAE.Exp inExp;
145 input Boolean inBoolean "impl";
146 input Absyn.Msg inMsg;
147 input Integer numIter;
148 output FCore.Cache outCache;
149 output Values.Value outValue;
150
151 partial function ReductionOperator
152 input Values.Value v1;
153 input Values.Value v2;
154 output Values.Value res;
155 end ReductionOperator;
156 algorithm
157 (outCache,outValue):=
158 matchcontinue (inCache, inEnv, inExp, inBoolean, inMsg)
159 local
160 Boolean impl;
161 FCore.Graph env;
162 Absyn.Msg msg;
163 list<Values.Value> vallst;
164 list<DAE.Exp> expl;
165 Values.Value newval,value;
166 DAE.Exp e;
167 Absyn.Path funcpath;
168 FCore.Cache cache;
169
170 // adrpo: TODO! this needs more work as if we don't have a symtab we run into unloading of dlls problem
171 case (cache, env, (e as DAE.CALL(path = funcpath,expLst = expl)), impl, msg)
172 algorithm
173 // do not handle Connection.isRoot here!
174
3/4
✓ Branch 1 taken 182 times.
✓ Branch 2 taken 13314 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 182 times.
13496 false := stringEq("Connection.isRoot", AbsynUtil.pathString(funcpath));
175 // do not roll back errors generated by evaluating the arguments
176 13496 (cache,vallst) := Ceval.cevalList(cache,env, expl, impl, msg, numIter);
177
178 13495 (cache,newval):= cevalCallFunction(cache, env, e, vallst, impl, msg, numIter+1);
179 then
180 (cache,newval);
181
182 // Try Interactive functions last
183 case (cache, env, (e as DAE.CALL()), (true), msg)
184 algorithm
185 11202 (cache,value) := cevalInteractiveFunctions(cache, env, e, msg, numIter+1);
186 then
187 (cache,value);
188 case (cache, env, e, impl, msg)
189 algorithm
190 14507 (cache,value) := Ceval.ceval(cache,env,e,impl,msg,numIter+1);
191 then
192 (cache,value);
193 end matchcontinue;
194 end ceval;
195
196 public function isCompleteFunction
197 "a function is complete if is:
198 - not partial
199 - not replaceable (without redeclare)
200 - replaceable and called functions are not partial or not replaceable (without redeclare)"
201 input FCore.Cache inCache;
202 input FCore.Graph inEnv;
203 input Absyn.Path inFuncPath;
204 output Boolean isComplete;
205 algorithm
206 isComplete := matchcontinue(inCache, inEnv, inFuncPath)
207 local
208 FCore.Cache cache;
209 FCore.Graph env;
210 Absyn.Path fpath;
211
212 // external functions are complete :)
213 case (cache, env, fpath)
214 algorithm
215
6/8
✗ Branch 1 not taken.
✓ Branch 2 taken 38028 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 38020 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 38020 times.
✓ Branch 7 taken 37970 times.
✓ Branch 8 taken 50 times.
38559 (_, SCode.CLASS(classDef = SCode.PARTS(externalDecl = SOME(_))), _) := Lookup.lookupClass(cache, env, fpath);
216 then
217 true;
218
219 // if is partial instantiation no function evaluation/generation
220 case (_, _, _)
221 algorithm
222
2/2
✓ Branch 1 taken 35852 times.
✓ Branch 2 taken 2657 times.
38509 true := System.getPartialInstantiation();
223 then
224 false;
225
226 // partial functions are not complete!
227 case (cache, env, fpath)
228 algorithm
229
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 35321 times.
✓ Branch 3 taken 35321 times.
✗ Branch 4 not taken.
35852 (_, SCode.CLASS(partialPrefix = SCode.PARTIAL()), _) := Lookup.lookupClass(cache, env, fpath);
230 then
231 false;
232
233 else true;
234
235 end matchcontinue;
236 end isCompleteFunction;
237
238 public function compileModel "Compiles a model given a file-prefix, helper function to buildModel."
239 input String fileprefix;
240 input list<String> libs;
241 input String workingDir = "";
242 input list<String> makeVars = {};
243 protected
244 String omhome = Settings.getInstallationDirectoryPath(),omhome_1 = System.stringReplace(omhome, "\"", "");
245 String pd = Autoconf.pathDelimiter;
246 String cdWorkingDir,setMakeVars,libsfilename,libs_str,s_call,winCompileMode,workDir = (if stringEq(workingDir, "") then "" else workingDir + pd), linkType = "dynamic";
247 String fileDLL = workDir + fileprefix + Autoconf.dllExt,
248 fileEXE = workDir + fileprefix + Autoconf.exeExt,
249 fileLOG = workDir + fileprefix + ".log";
250 Integer numParallel;
251 Boolean isWindows = Autoconf.os == "Windows_NT";
252 list<String> makeVarsNoBinding;
253 algorithm
254 1376 libsfilename := workDir + fileprefix + ".libs";
255 1376 libs_str := stringDelimitList(libs, " ");
256 makeVarsNoBinding := makeVars; // OMC is stupid and wants to constant evaluate inputs with bindings for iterator variables...
257
258 1376 System.writeFile(libsfilename, libs_str);
259 if isWindows then
260 // We only need to set OPENMODELICAHOME on Windows, and set doesn't work in bash shells anyway
261 // adrpo: 2010-10-05:
262 // whatever you do, DO NOT add a space before the && otherwise
263 // OPENMODELICAHOME that we set will contain a SPACE at the end!
264 // set OPENMODELICAHOME=DIR && actually adds the space between the DIR and &&
265 // to the environment variable! Don't ask me why, ask Microsoft.
266 omhome := "set OPENMODELICAHOME=" + System.stringReplace(omhome_1, "/", "\\") + "&& ";
267 setMakeVars := sum("set "+var+"&& " for var in makeVarsNoBinding);
268 cdWorkingDir := if stringEmpty(workingDir) then "" else ("cd \"" + workingDir + "\"&& ");
269 winCompileMode := if Testsuite.isRunning() then "serial" else "parallel";
270 if Flags.getConfigEnum(Flags.LINK_TYPE) == 1 then
271 linkType := "static";
272 elseif Flags.getConfigEnum(Flags.LINK_TYPE) == 2 then
273 linkType := "dynamic";
274 end if;
275 linkType := if Testsuite.isRunning() then "dynamic" else linkType;
276 s_call := stringAppendList({omhome,cdWorkingDir,setMakeVars,"\"",omhome_1,pd,"share",pd,"omc",pd,"scripts",pd,"Compile","\""," ",fileprefix," ",Config.simulationCodeTarget()," ", System.openModelicaPlatform(), " ", winCompileMode, " ", linkType});
277 else
278
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1374 times.
1376 numParallel := if Testsuite.isRunning() then 1 else Config.noProc();
279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1376 times.
1376 cdWorkingDir := if stringEmpty(workingDir) then "" else (" -C \"" + workingDir + "\"");
280
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1376 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1376 times.
1376 setMakeVars := sum(" "+var for var in makeVarsNoBinding);
281 2752 s_call := stringAppendList({Autoconf.make," -j",intString(numParallel),cdWorkingDir," -f ",fileprefix,".makefile",setMakeVars});
282 end if;
283
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1376 times.
1376 if Flags.isSet(Flags.DYN_LOAD) then
284 ✗ Debug.traceln("compileModel: running " + s_call);
285 end if;
286
287 // remove .exe .dll .log!
288
2/2
✓ Branch 1 taken 86 times.
✓ Branch 2 taken 1290 times.
1376 if System.regularFileExists(fileEXE) then
289
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 86 times.
86 0 := System.removeFile(fileEXE);
290 end if;
291
2/2
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 1319 times.
1376 if System.regularFileExists(fileDLL) then
292
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 0 := System.removeFile(fileDLL);
293 end if;
294
2/2
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 1232 times.
1376 if System.regularFileExists(fileLOG) then
295
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
144 0 := System.removeFile(fileLOG);
296 end if;
297
298
2/2
✓ Branch 1 taken 1374 times.
✓ Branch 2 taken 2 times.
1376 if Testsuite.isRunning() then
299 1374 System.appendFile(Testsuite.getTempFilesFile(),
300 fileEXE + "\n" + fileDLL + "\n" + fileLOG + "\n" + fileprefix + ".o\n" + fileprefix + ".libs\n" +
301 fileprefix + "_records.o\n" + fileprefix + "_res.mat\n");
302 end if;
303
304 // call the system command to compile the model!
305
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1375 times.
1376 if System.systemCall(s_call,if isWindows then "" else fileLOG) <> 0 then
306 // We failed, print error
307
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 if System.regularFileExists(fileLOG) then
308 2 Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {System.readFile(fileLOG)});
309 elseif isWindows then
310 // Check that it is a correct OPENMODELICAHOME, on Windows only
311 s_call := stringAppendList({omhome_1,pd,"share",pd,"omc",pd,"scripts",pd,"Compile.bat"});
312 if not System.regularFileExists(s_call) then
313 Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {stringAppendList({"command ",s_call," not found. Check $OPENMODELICAHOME"})});
314 end if;
315 end if;
316
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if Flags.isSet(Flags.DYN_LOAD) then
317 ✗ Debug.trace("compileModel: failed!\n");
318 end if;
319 1 fail();
320 end if;
321
322
1/2
✓ Branch 1 taken 1375 times.
✗ Branch 2 not taken.
1375 if Flags.isSet(Flags.DYN_LOAD) then
323 ✗ Debug.trace("compileModel: successful!\n");
324 end if;
325 end compileModel;
326
327 public function loadFile "load the file or the directory structure if the file is named package.mo"
328 input String inName;
329 input String encoding;
330 input Absyn.Program p;
331 input Boolean checkUses;
332 input Boolean notifyLoad;
333 input Boolean requireExactVersion;
334 input Boolean allowWithin = true;
335 output Absyn.Program outProgram;
336 protected
337 String dir,name=inName,filename,cname,prio,mp,msg;
338 list<String> rest;
339 algorithm
340 // If the name refers to a directory, try to load a package.mo inside it instead.
341
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2023 times.
2024 if System.directoryExists(inName) then
342 1 name := inName + Autoconf.pathDelimiter + "package.mo";
343 end if;
344
345
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2022 times.
2024 if not System.regularFileReadable(name) then
346
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if not System.regularFileExists(name) then
347 msg := "file does not exist";
348 else
349 msg := "read access denied";
350 end if;
351
352 2 Error.addMessage(Error.LOAD_FILE_FAILED, {name, msg});
353 2 fail();
354 end if;
355
356 2022 (dir,filename) := Util.getAbsoluteDirectoryAndFile(name);
357
7/8
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 1915 times.
✓ Branch 3 taken 60 times.
✓ Branch 4 taken 47 times.
✓ Branch 5 taken 69 times.
✓ Branch 6 taken 1906 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 69 times.
2022 if filename == "package.mo" or filename == "package.moc" then
358
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 47 times.
47 cname::rest := System.strtok(List.last(System.strtok(dir,"/"))," ");
359 47 prio := stringDelimitList(rest, " ");
360 // send "" priority if that is it, don't send "default"
361 // see https://trac.openmodelica.org/OpenModelica/ticket/2422
362 // prio = if_(stringEq(prio,""), "default", prio);
363 47 mp := System.realpath(dir + "/../") + Autoconf.groupDelimiter + Settings.getModelicaPath(Testsuite.isRunning());
364
2/6
✗ Branch 3 not taken.
✓ Branch 4 taken 47 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 47 times.
141 (outProgram,true) := loadModel((Absyn.IDENT(cname),"loadFile automatically converted to loadModel",{prio},true)::{}, mp, p, true, notifyLoad, checkUses, requireExactVersion, filename == "package.moc", pathToFile=System.realpath(name));
365 47 return;
366 end if;
367 1975 outProgram := Parser.parse(name,encoding);
368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1958 times.
1958 if not allowWithin then
369 ✗ checkTopClassWithin(outProgram, name);
370 end if;
371 1958 ClassLoader.checkOnLoadMessage(outProgram);
372
373 // Check if we have duplicate top level classes before calling checkUsesAndUpdateProgram()
374 // which will update the program by repeatedly replacing duplicate classes with last one seen.
375
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1957 times.
1958 if checkDuplicateTopLevelClasses(outProgram) then
376 1 fail();
377 end if;
378
379 1957 outProgram := checkUsesAndUpdateProgram(outProgram, p, checkUses, Settings.getModelicaPath(Testsuite.isRunning()), notifyLoad, requireExactVersion);
380 end loadFile;
381
382 protected function checkDuplicateTopLevelClasses
383 input Absyn.Program program;
384 output Boolean hasDuplicates = false;
385 protected
386 Boolean skip;
387 list<SourceInfo> infos;
388 UnorderedMap<String, Absyn.Info> classInfoMap;
389 Option<Absyn.Info> optClassInfo;
390 algorithm
391
392
2/2
✓ Branch 1 taken 1206 times.
✓ Branch 2 taken 752 times.
1958 if listLength(program.classes) < 2 then
393 1206 return;
394 end if;
395
396 752 classInfoMap := UnorderedMap.new<Absyn.Info>(stringHashDjb2, stringEq);
397
2/2
✓ Branch 0 taken 2137 times.
✓ Branch 1 taken 751 times.
2888 for cl in program.classes loop
398 () := match cl
399 case Absyn.CLASS(info=SOURCEINFO())
400 algorithm
401 // If the class comes from the interactive env or builtin files, ignore it.
402
7/12
✗ Branch 0 not taken.
✓ Branch 1 taken 2137 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 6 taken 128 times.
✓ Branch 7 taken 2009 times.
✓ Branch 10 taken 128 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 83 times.
✓ Branch 14 taken 2054 times.
✓ Branch 17 taken 83 times.
✗ Branch 18 not taken.
2137 skip := stringEq(cl.info.fileName,"<interactive>")
403 or stringEq(System.basename(cl.info.fileName), "ModelicaBuiltin.mo")
404 or stringEq(System.basename(cl.info.fileName), "MetaModelicaBuiltin.mo");
405
406 if not skip then
407 2137 optClassInfo := UnorderedMap.get(cl.name, classInfoMap);
408
409
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2137 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 2136 times.
2137 if isSome(optClassInfo) then
410 // It is a duplicate named top level class. Print error and return.
411 1 infos := {Util.getOption(optClassInfo), cl.info};
412 1 Error.addMultiSourceMessage(Error.DOUBLE_DECLARATION_OF_ELEMENTS, {cl.name}, infos);
413 hasDuplicates := true;
414 1 return;
415 else
416 // It is not a duplicate yet. Add it to the map and continue.
417 2136 UnorderedMap.add(cl.name, cl.info, classInfoMap);
418 end if;
419
420 end if;
421 then ();
422 else ();
423 end match;
424 end for;
425 end checkDuplicateTopLevelClasses;
426
427 protected function checkTopClassWithin
428 input Absyn.Program program;
429 input String filename;
430 algorithm
431 ✗ if not AbsynUtil.withinEqual(program.within_, Absyn.Within.TOP()) then
432 ✗ Error.addSourceMessage(Error.LIBRARY_UNEXPECTED_WITHIN,
433 {AbsynUtil.withinString(Absyn.Within.TOP()), AbsynUtil.withinString(program.within_)},
434 SOURCEINFO(filename, false, 1, 0, 1, 0, 0)
435 );
436 ✗ fail();
437 end if;
438 end checkTopClassWithin;
439
440 protected function checkUsesAndUpdateProgram
441 input Absyn.Program newp;
442 input output Absyn.Program p;
443 input Boolean checkUses;
444 input String modelicaPath;
445 input Boolean notifyLoad;
446 input Boolean requireExactVersion;
447 input Boolean mergeAST = false;
448 protected
449 list<tuple<Absyn.Path,String,list<String>,Boolean>> modelsToLoad;
450 algorithm
451
2/2
✓ Branch 0 taken 3474 times.
✓ Branch 1 taken 1 time.
3475 modelsToLoad := if checkUses then Interactive.getUsesAnnotationOrDefault(newp, requireExactVersion) else {};
452 3475 p := ProgramUtil.updateProgram(newp, p, mergeAST);
453 3475 (p, _) := loadModel(modelsToLoad, modelicaPath, p, false, notifyLoad, checkUses, requireExactVersion, false);
454 end checkUsesAndUpdateProgram;
455
456 public function loadModel
457 input list<tuple<Absyn.Path,String,list<String>,Boolean /* Only use the first entry on the OPENMODELICALIBRARY (MODELICAPATH in the language specification) */>> imodelsToLoad;
458 input String modelicaPath;
459 input Absyn.Program ip;
460 input Boolean forceLoad;
461 input Boolean notifyLoad;
462 input Boolean checkUses;
463 input Boolean requireExactVersion;
464 input Boolean encrypted = false;
465 input String pathToFile = "";
466 output Absyn.Program pnew = ip;
467 output Boolean success = true;
468 protected
469 Boolean b;
470 algorithm
471 5857 PackageManagement.installCachedPackages();
472
473
2/2
✓ Branch 0 taken 1963 times.
✓ Branch 1 taken 5857 times.
7820 for m in imodelsToLoad loop
474 1963 (pnew, b) := loadModel1(m, modelicaPath, forceLoad, notifyLoad,
475 checkUses, requireExactVersion, encrypted, pathToFile, pnew);
476
3/4
✓ Branch 0 taken 1570 times.
✓ Branch 1 taken 393 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1570 times.
1963 success := b and success;
477 end for;
478 end loadModel;
479
480 protected function loadModel1
481 input tuple<Absyn.Path,String,list<String>,Boolean> modelToLoad;
482 input String modelicaPath;
483 input Boolean forceLoad;
484 input Boolean notifyLoad;
485 input Boolean checkUses;
486 input Boolean requireExactVersion;
487 input Boolean encrypted;
488 input String pathToFile;
489 input output Absyn.Program program;
490 output Boolean success = true;
491 protected
492 list<tuple<Absyn.Path,String,list<String>,Boolean>> modelsToLoad;
493 Boolean onlyCheckFirstModelicaPath;
494 Absyn.Path path;
495 list<String> versionsLst;
496 String pathStr, versions, version, thisModelicaPath, dir, requestedBy;
497 Absyn.Program pnew;
498 ErrorTypes.MessageTokens msgTokens;
499 Option<Absyn.Class> cl;
500 algorithm
501 1963 (path, requestedBy, versionsLst, onlyCheckFirstModelicaPath) := modelToLoad;
502
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 1916 times.
1963 if onlyCheckFirstModelicaPath then
503 /* Using loadFile() */
504
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
47 thisModelicaPath::_ := System.strtok(modelicaPath, Autoconf.groupDelimiter);
505 else
506 thisModelicaPath := modelicaPath;
507 end if;
508 try
509
2/2
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 1905 times.
1963 if checkModelLoaded(modelToLoad, program, forceLoad, NONE()) then
510 pnew := Absyn.PROGRAM({}, Absyn.TOP());
511 version := "";
512 58 return;
513 else
514
3/4
✓ Branch 0 taken 1858 times.
✓ Branch 1 taken 47 times.
✓ Branch 3 taken 1858 times.
✗ Branch 4 not taken.
1905 if pathToFile=="" then
515 1858 pnew := ClassLoader.loadClass(path, versionsLst, thisModelicaPath, NONE(), requireExactVersion, encrypted);
516 else
517 47 dir := System.dirname(pathToFile);
518 47 cl := ClassLoader.loadClassFromMp(AbsynUtil.pathFirstIdent(path), System.dirname(dir), System.basename(dir), true, NONE(), encrypted);
519
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
✓ Branch 2 taken 47 times.
✗ Branch 3 not taken.
47 if (isSome(cl)) then
520 94 pnew := Absyn.PROGRAM({Util.getOption(cl)}, Absyn.TOP());
521 else
522 pnew := Absyn.PROGRAM({}, Absyn.TOP());
523 end if;
524 end if;
525
526 1511 checkPatchedModelicaServices(AbsynUtil.pathFirstIdent(path), pnew);
527
528
2/2
✓ Branch 0 taken 205 times.
✓ Branch 1 taken 1306 times.
1511 if notifyLoad and not forceLoad then
529 205 version := getPackageVersion(path, pnew);
530 205 msgTokens := {AbsynUtil.pathString(path), version, requestedBy};
531 205 Error.addMessage(Error.NOTIFY_LOAD_MODEL_DUE_TO_USES, msgTokens);
532 205 System.loadModelCallBack(AbsynUtil.pathFirstIdent(path));
533 end if;
534 end if;
535
536 1511 program := ProgramUtil.updateProgram(pnew, program);
537
538
2/2
✓ Branch 0 taken 1510 times.
✓ Branch 1 taken 1 time.
1511 if checkUses then
539 1510 modelsToLoad := Interactive.getUsesAnnotationOrDefault(pnew, requireExactVersion);
540 1510 (program, success) := loadModel(modelsToLoad, modelicaPath, program, false, notifyLoad, checkUses, requireExactVersion, false);
541 end if;
542 else
543 394 pathStr := AbsynUtil.pathString(path);
544 394 versions := stringDelimitList(versionsLst, ",");
545 394 msgTokens := {pathStr, versions, thisModelicaPath};
546
2/2
✓ Branch 0 taken 393 times.
✓ Branch 1 taken 1 time.
394 if forceLoad then
547 393 Error.addMessage(Error.LOAD_MODEL_FAILED, msgTokens);
548 393 success := false;
549 else
550 1 Error.addMessage(Error.NOTIFY_LOAD_MODEL_FAILED, msgTokens);
551 end if;
552 end try;
553 end loadModel1;
554
555 protected function checkModelLoaded
556 input tuple<Absyn.Path,String,list<String>,Boolean> tpl;
557 input Absyn.Program p;
558 input Boolean forceLoad;
559 input Option<String> failNonLoad;
560 output Boolean loaded;
561 algorithm
562 loaded := matchcontinue (tpl, forceLoad, failNonLoad)
563 local
564 Absyn.Class cdef;
565 String str1,str2,requestOrigin;
566 Option<String> ostr2;
567 Absyn.Path path;
568 list<String> withoutConversion,withConversion;
569
570 case (_, true, _) then false;
571 case ((path,requestOrigin,str1::_,_), false, _)
572 algorithm
573 1091 cdef := ProgramUtil.getPathedClassInProgram(path,p);
574 58 ostr2 := AbsynUtil.getNamedAnnotationInClass(cdef,Absyn.IDENT("version"),Interactive.getAnnotationStringValueOrFail);
575 58 (withoutConversion,withConversion) := Interactive.getConversionAnnotation(cdef);
576 58 checkValidVersion(path,str1,ostr2,requestOrigin=requestOrigin,withConversion=withConversion,withoutConversion=withoutConversion);
577 then true;
578 case (_, _, NONE()) then false;
579 case ((path,_,_,_), _, SOME(str2))
580 algorithm
581 ✗ str1 := AbsynUtil.pathString(path);
582 ✗ Error.addMessage(Error.INST_NON_LOADED, {str1,str2});
583 then false;
584 end matchcontinue;
585 end checkModelLoaded;
586
587 protected function checkValidVersion
588 input Absyn.Path path;
589 input String version;
590 input Option<String> actualVersion;
591 input String requestOrigin;
592 input list<String> withConversion;
593 input list<String> withoutConversion;
594 protected
595 SemanticVersion.Version semverWanted, semverActual;
596 String actualVersionStr, pathStr;
597 algorithm
598 58 semverWanted := SemanticVersion.parse(version);
599 58 actualVersionStr := Util.getOptionOrDefault(actualVersion, "");
600 58 pathStr := AbsynUtil.pathString(path);
601 58 semverActual := SemanticVersion.parse(actualVersionStr);
602
1/2
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
58 if 0 == SemanticVersion.compare(semverWanted, semverActual, comparePrerelease=false) then
603 58 return;
604 end if;
605 ✗ if not (SemanticVersion.isSemVer(semverActual) and SemanticVersion.isSemVer(semverWanted)) then
606 ✗ Error.addMessage(Error.LOAD_MODEL_DIFFERENT_VERSIONS, {pathStr, version, actualVersionStr});
607 ✗ return;
608 end if;
609 ✗ for ver in withoutConversion loop
610 ✗ if 0 == SemanticVersion.compare(semverWanted, SemanticVersion.parse(ver), comparePrerelease=false) then
611 ✗ Error.addMessage(Error.LOAD_MODEL_DIFFERENT_VERSIONS_WITHOUT_CONVERSION, {requestOrigin, pathStr, version, actualVersionStr});
612 ✗ return;
613 end if;
614 end for;
615 ✗ for ver in withConversion loop
616 ✗ if 0 == SemanticVersion.compare(semverWanted, SemanticVersion.parse(ver), comparePrerelease=false) then
617 ✗ Error.addMessage(Error.LOAD_MODEL_DIFFERENT_VERSIONS_WITH_CONVERSION, {requestOrigin, pathStr, version, actualVersionStr});
618 ✗ return;
619 end if;
620 end for;
621 ✗ if SemanticVersion.compare(semverWanted, semverActual) > 0 then
622 ✗ Error.addMessage(Error.LOAD_MODEL_DIFFERENT_VERSIONS_NEWER, {pathStr, version, actualVersionStr});
623 else
624 ✗ Error.addMessage(Error.LOAD_MODEL_DIFFERENT_VERSIONS_OLDER, {pathStr, version, actualVersionStr});
625 end if;
626 end checkValidVersion;
627
628 protected function checkPatchedModelicaServices
629 "Checks if the library is ModelicaServices, and issues a warning if it
630 doesn't appear to have been patched for use with OpenModelica."
631 input String name;
632 input Absyn.Program program;
633 protected
634 Absyn.Class cls;
635 Absyn.Algorithm alg;
636 Absyn.ComponentRef fn;
637 algorithm
638
3/4
✓ Branch 0 taken 461 times.
✓ Branch 1 taken 1050 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 461 times.
1511 if name == "ModelicaServices" then
639 try
640 // Try to look up ModelicaServices.ExternalReferences.loadResource.
641 461 cls := ProgramUtil.getPathedClassInProgram(Absyn.Path.QUALIFIED("ModelicaServices",
642 Absyn.Path.QUALIFIED("ExternalReferences", Absyn.Path.IDENT("loadResource"))), program);
643 // Check if the first statement in the first algorithm section is a function call.
644
4/8
✗ Branch 2 not taken.
✓ Branch 3 taken 461 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 461 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 461 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 461 times.
461 Absyn.ClassPart.ALGORITHMS(contents = {Absyn.AlgorithmItem.ALGORITHMITEM(algorithm_ = alg)}) :=
645 List.find(AbsynUtil.getClassPartsInClass(cls), AbsynUtil.isAlgorithmSection);
646
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 461 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 461 times.
461 Absyn.Algorithm.ALG_ASSIGN(value = Absyn.Exp.CALL(function_ = fn)) := alg;
647
648 // Issue a warning if that function call is not a call to our uriToFilename.
649
2/4
✓ Branch 1 taken 461 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 461 times.
461 if AbsynUtil.crefString(fn) <> "OpenModelica.Scripting.uriToFilename" then
650 ✗ Error.addMessage(Error.UNPATCHED_MODELICA_SERVICES, {});
651 end if;
652 else
653 end try;
654 end if;
655 end checkPatchedModelicaServices;
656
657 public function cevalInteractiveFunctions
658 "defined in the interactive environment."
659 input FCore.Cache inCache;
660 input FCore.Graph inEnv;
661 input DAE.Exp inExp "expression to evaluate";
662 input Absyn.Msg msg;
663 input Integer numIter;
664 output FCore.Cache outCache;
665 output Values.Value outValue;
666 algorithm
667 (outCache,outValue) := matchcontinue (inCache, inEnv, inExp)
668 local
669 FCore.Cache cache;
670 FCore.Graph env;
671 DAE.Exp exp;
672 list<DAE.Exp> eLst;
673 list<Values.Value> valLst;
674 String name;
675 Values.Value value;
676 Real t1,t2,t;
677
678 // This needs to be first because otherwise it takes 0 time to get the value :)
679 case (cache, env, DAE.CALL(path = Absyn.IDENT(name = "timing"),expLst = {exp}))
680 algorithm
681 ✗ t1 := System.time();
682 ✗ (cache,_) := Ceval.ceval(cache,env, exp, true, msg,numIter+1);
683 ✗ t2 := System.time();
684 ✗ t := t2 - t1;
685 ✗ then
686 (cache,Values.REAL(t));
687
688 case (cache, env, DAE.CALL(path=Absyn.IDENT(name),attr=DAE.CALL_ATTR(builtin=true),expLst=eLst))
689 algorithm
690 22184 (cache,valLst) := Ceval.cevalList(cache,env,eLst,true,msg,numIter);
691 22043 valLst := List.map1(valLst,evalCodeTypeName,env);
692 22043 (cache,value) := cevalInteractiveFunctions2(cache,env,name,valLst,msg);
693 then
694 (cache,value);
695
696 end matchcontinue;
697 end cevalInteractiveFunctions;
698
699 public function cevalInteractiveFunctions2
700 "defined in the interactive environment."
701 input FCore.Cache cache;
702 input FCore.Graph env;
703 input String functionName;
704 input list<Values.Value> args;
705 input Absyn.Msg msg;
706 output FCore.Cache outCache = cache;
707 output Values.Value outValue;
708 algorithm
709 outValue := matchcontinue (functionName, args)
710 local
711 String str,str1,str2,str3,token,cmd,encoding,filename,pathstr,name,res,workdir,from,to;
712 list<Values.Value> vals, cvars;
713 Absyn.Path path,classpath,className,parentClass;
714 SCode.Program sp;
715 Absyn.Program p,newp,parsed;
716 list<Absyn.Program> newps;
717 DAE.Type ty;
718 list<DAE.Type> tys;
719 Values.Value v;
720 Integer i;
721 Access access;
722 list<String> strs, strs1, strs2, interfaceType;
723 Real r,r1,r2;
724 Boolean bval, b, b1, mergeAST, includePartial, sort, requireExactVersion, allowWithin;
725 Absyn.CodeNode codeNode;
726 list<Absyn.Path> paths;
727 list<Absyn.Class> classes;
728 Absyn.Within within_;
729 Config.LanguageStandard oldLanguageStd;
730 SCode.Element cl;
731 list<SCode.Element> elts;
732 list<ErrorTypes.TotalMessage> messages;
733 list<tuple<String,list<String>>> interfaceTypeAssoc;
734 GCExt.ProfStats gcStats;
735
736 case ("parseString",{Values.STRING(str1),Values.STRING(str2)})
737 algorithm
738 4 Absyn.PROGRAM(classes=classes,within_=within_) := Parser.parsestring(str1,str2);
739
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
5 paths := list(Absyn.Path.IDENT(AbsynUtil.className(c)) for c in classes);
740 3 paths := List.map1r(paths,AbsynUtil.joinWithinPath,within_);
741 3 then
742 ValuesMake.makeCodeTypeNameArray(paths);
743
744 case ("parseString",_)
745 1 then ValuesMake.makeArray({});
746
747 case ("parseFile",{Values.STRING(str1),Values.STRING(encoding)})
748 algorithm
749 // clear the errors before!
750 ✗ Error.clearMessages() "Clear messages";
751 ✗ Print.clearErrorBuf() "Clear error buffer";
752 ✗ paths := Interactive.parseFile(str1, encoding);
753 ✗ then
754 ValuesMake.makeCodeTypeNameArray(paths);
755
756 case ("loadFileInteractiveQualified",{Values.STRING(str1),Values.STRING(encoding)})
757 algorithm
758 // clear the errors before!
759 2 Error.clearMessages() "Clear messages";
760 2 Print.clearErrorBuf() "Clear error buffer";
761 2 paths := Interactive.parseFile(str1, encoding, updateProgram=true);
762 2 then
763 ValuesMake.makeCodeTypeNameArray(paths);
764
765 case ("loadFileInteractive",{Values.STRING(str1),Values.STRING(encoding),Values.BOOL(b),Values.BOOL(b1),Values.BOOL(requireExactVersion)})
766 algorithm
767 ✗ newp := loadFile(str1, encoding, SymbolTable.getAbsyn(), b, b1, requireExactVersion) "System.regularFileExists(name) => 0 & Parser.parse(name) => p1 &" ;
768 ✗ vals := List.map(Interactive.getTopClassnames(newp),ValuesMake.makeCodeTypeName);
769 ✗ SymbolTable.setAbsyn(newp);
770 ✗ then
771 ValuesMake.makeArray(vals);
772
773 case ("getSourceFile",{Values.CODE(Absyn.C_TYPENAME(path))})
774 algorithm
775 ✗ str := Interactive.getSourceFile(path, SymbolTable.getAbsyn());
776 ✗ then
777 Values.STRING(str);
778
779 case ("setSourceFile",{Values.CODE(Absyn.C_TYPENAME(path)),Values.STRING(str)})
780 algorithm
781 1 access := Interactive.checkAccessAnnotationAndEncryption(path, SymbolTable.getAbsyn());
782
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if access >= Access.all then // i.e., The class is not encrypted.
783 1 (b,p) := Interactive.setSourceFile(path, str, SymbolTable.getAbsyn());
784 1 SymbolTable.setAbsyn(p);
785 else
786 ✗ Error.addMessage(Error.SAVE_ENCRYPTED_CLASS_ERROR, {});
787 ✗ b := false;
788 end if;
789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
790 Values.BOOL(b);
791
792 case ("basename",{Values.STRING(str)})
793 ✗ then Values.STRING(System.basename(str));
794
795 case ("dirname",{Values.STRING(str)})
796 ✗ then Values.STRING(System.dirname(str));
797
798 case ("codeToString",{Values.CODE(codeNode)})
799 ✗ then Values.STRING(Dump.printCodeStr(codeNode));
800
801 case ("typeOf",{Values.CODE(Absyn.C_VARIABLENAME(Absyn.CREF_IDENT(name = name)))})
802 algorithm
803 ✗ ty := Interactive.getTypeOfVariable(name, SymbolTable.getVars());
804 ✗ then
805 Values.STRING(TypesDump.unparseType(ty));
806
807 case ("GC_gcollect_and_unmap",{})
808 algorithm
809 ✗ GCExt.gcollectAndUnmap();
810 then
811 Values.BOOL(true);
812
813 case ("GC_expand_hp",{Values.INTEGER(i)})
814
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 140 times.
140 then Values.BOOL(GCExt.expandHeap(i));
815
816 case ("GC_set_max_heap_size",{Values.REAL(r)})
817 algorithm
818 ✗ GCExt.setMaxHeapSize(r);
819 then
820 Values.BOOL(true);
821
822 case ("GC_set_max_heap_size",{Values.INTEGER(i)})
823 algorithm
824 ✗ GCExt.setMaxHeapSize(i);
825 then
826 Values.BOOL(true);
827
828 case ("GC_get_prof_stats",{})
829 algorithm
830 ✗ gcStats := GCExt.getProfStats();
831 ✗ then
832 Values.RECORD(Absyn.IDENT("GC_PROFSTATS"),
833 {
834 Values.INTEGER(gcStats.heapsize_full),
835 Values.INTEGER(gcStats.free_bytes_full),
836 Values.INTEGER(gcStats.unmapped_bytes),
837 Values.INTEGER(gcStats.bytes_allocd_since_gc),
838 Values.INTEGER(gcStats.allocd_bytes_before_gc),
839 Values.INTEGER(gcStats.bytes_allocd_since_gc+gcStats.allocd_bytes_before_gc),
840 Values.INTEGER(gcStats.non_gc_bytes),
841 Values.INTEGER(gcStats.gc_no),
842 Values.INTEGER(gcStats.markers_m1),
843 Values.INTEGER(gcStats.bytes_reclaimed_since_gc),
844 Values.INTEGER(gcStats.reclaimed_bytes_before_gc)
845 },
846 {
847 "heapsize_full",
848 "free_bytes_full",
849 "unmapped_bytes",
850 "bytes_allocd_since_gc",
851 "allocd_bytes_before_gc",
852 "total_allocd_bytes",
853 "non_gc_bytes",
854 "gc_no",
855 "markers_m1",
856 "bytes_reclaimed_since_gc",
857 "reclaimed_bytes_before_gc"
858 },
859 -1);
860
861 case ("clear",{})
862 algorithm
863 5 SymbolTable.reset();
864 5 NFApi.clearCache();
865 then
866 Values.BOOL(true);
867
868 case ("clearProgram",{})
869 algorithm
870 1 SymbolTable.clearProgram();
871 1 NFApi.clearCache();
872 then
873 Values.BOOL(true);
874
875 case ("clearVariables",{})
876 algorithm
877 ✗ SymbolTable.setVars({});
878 then
879 Values.BOOL(true);
880
881 98 case ("list", _) then listClass(args);
882 5 case ("listFile", _) then listFile(args);
883
884 case ("sortStrings",{Values.ARRAY(valueLst=vals)})
885 algorithm
886 ✗ strs := List.map(vals, ValuesUtil.extractValueString);
887 ✗ strs := List.sort(strs, Util.strcmpBool);
888 ✗ then
889 ValuesMake.makeArray(List.map(strs,ValuesMake.makeString));
890
891 case ("listVariables",{})
892 ✗ then ValuesMake.makeArray(getVariableNames(SymbolTable.getVars(),{}));
893
894 case ("setTempDirectoryPath",{Values.STRING(cmd)})
895 algorithm
896 // cmd = Util.rawStringToInputString(cmd);
897 ✗ Settings.setTempDirectoryPath(cmd);
898 then
899 Values.BOOL(true);
900
901 case ("getTempDirectoryPath",{})
902 ✗ then Values.STRING(Settings.getTempDirectoryPath());
903
904 case ("setEnvironmentVar",{Values.STRING(name), Values.STRING(str)})
905 ✗ then Values.BOOL(System.setEnv(name, str, true) == 0);
906
907 case ("getEnvironmentVar",{Values.STRING(name)})
908 657 then Values.STRING(Util.makeValueOrDefault(System.readEnv, name, ""));
909
910 case ("setInstallationDirectoryPath",{Values.STRING(cmd)})
911 algorithm
912 // cmd = Util.rawStringToInputString(cmd);
913 ✗ Settings.setInstallationDirectoryPath(cmd);
914 then
915 Values.BOOL(true);
916
917 case ("getInstallationDirectoryPath",{})
918 17 then Values.STRING(Settings.getInstallationDirectoryPath());
919
920 case ("getModelicaPath",{})
921 ✗ then Values.STRING(Settings.getModelicaPath(Testsuite.isRunning()));
922
923 case ("setModelicaPath",{Values.STRING(cmd)})
924 algorithm
925 // cmd = Util.rawStringToInputString(cmd);
926 1 Settings.setModelicaPath(cmd);
927 1 setGlobalRoot(Global.packageIndexCacheIndex, 0);
928 then
929 Values.BOOL(true);
930
931 case ("setModelicaPath",_)
932 then Values.BOOL(false);
933
934 case ("getHomeDirectoryPath",{})
935 ✗ then Values.STRING(Settings.getHomeDir(Testsuite.isRunning()));
936
937 case ("getLanguageStandard",{})
938 ✗ then Values.STRING(Config.languageStandardString(Config.getLanguageStandard()));
939
940 case ("reopenStandardStream",{Values.ENUM_LITERAL(index=i),Values.STRING(filename)})
941 ✗ then Values.BOOL(System.reopenStandardStream(i-1,filename));
942
943 case ("iconv",{Values.STRING(str),Values.STRING(from),Values.STRING(to)})
944 ✗ then Values.STRING(System.iconv(str,from,to));
945
946 case ("getCompiler",{})
947 ✗ then Values.STRING(System.getCCompiler());
948
949 case ("setCFlags",{Values.STRING(str)})
950 algorithm
951 2 System.setCFlags(str);
952 then
953 Values.BOOL(true);
954
955 case ("getCFlags",{})
956 2 then Values.STRING(System.getCFlags());
957
958 case ("setCompiler",{Values.STRING(str)})
959 algorithm
960 1 System.setCCompiler(str);
961 then
962 Values.BOOL(true);
963
964 case ("getCXXCompiler",{})
965 ✗ then Values.STRING(System.getCXXCompiler());
966
967 case ("setCXXCompiler",{Values.STRING(str)})
968 algorithm
969 1 System.setCXXCompiler(str);
970 then
971 Values.BOOL(true);
972
973 case ("setCompilerFlags",{Values.STRING(str)})
974 algorithm
975 ✗ System.setCFlags(str);
976 then
977 Values.BOOL(true);
978
979 case ("getLinker",{})
980 ✗ then Values.STRING(System.getLinker());
981
982 case ("setLinker",{Values.STRING(str)})
983 algorithm
984 ✗ System.setLinker(str);
985 then
986 Values.BOOL(true);
987
988 case ("getLinkerFlags",{})
989 ✗ then Values.STRING(System.getLDFlags());
990
991 case ("setLinkerFlags",{Values.STRING(str)})
992 algorithm
993 ✗ System.setLDFlags(str);
994 then
995 Values.BOOL(true);
996
997 case ("setCommandLineOptions",{Values.STRING(str)})
998 algorithm
999 904 b := Flags.isSet(Flags.SCODE_INST);
1000 904 strs := System.strtok(str, " ");
1001
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 902 times.
904 {} := FlagsUtil.readArgs(strs);
1002 902 FlagsUtil.applyNumProcEnvironment();
1003 902 outCache := FCore.emptyCache();
1004
1005
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 891 times.
902 if b <> Flags.isSet(Flags.SCODE_INST) then
1006 11 Builtin.clearInitialGraph();
1007 end if;
1008 then
1009 Values.BOOL(true);
1010
1011 case ("setCommandLineOptions",_)
1012 then Values.BOOL(false);
1013
1014 case ("getCommandLineOptions", {})
1015 ✗ then ValuesMake.makeStringArray(FlagsUtil.unparseFlags());
1016
1017 case ("getCommandLineOptions", _)
1018 then Values.META_FAIL();
1019
1020 case ("clearCommandLineOptions", {})
1021 algorithm
1022 ✗ FlagsUtil.resetDebugFlags();
1023 ✗ FlagsUtil.resetConfigFlags();
1024 then
1025 Values.BOOL(true);
1026
1027 case ("clearCommandLineOptions",_)
1028 then Values.BOOL(false);
1029
1030 case ("enableNewInstantiation",_)
1031 algorithm
1032 ✗ if not Flags.isSet(Flags.SCODE_INST) then
1033 ✗ Builtin.clearInitialGraph();
1034 ✗ FlagsUtil.enableDebug(Flags.SCODE_INST);
1035 ✗ outCache := FCore.emptyCache();
1036 end if;
1037 then
1038 Values.BOOL(true);
1039
1040 case ("enableNewInstantiation",_)
1041 then Values.BOOL(false);
1042
1043 case ("disableNewInstantiation",_)
1044 algorithm
1045 ✗ if Flags.isSet(Flags.SCODE_INST) then
1046 ✗ FlagsUtil.disableDebug(Flags.SCODE_INST);
1047 ✗ outCache := FCore.emptyCache();
1048 ✗ Builtin.clearInitialGraph();
1049 end if;
1050 then
1051 Values.BOOL(true);
1052
1053 case ("disableNewInstantiation",_)
1054 then
1055 Values.BOOL(false);
1056
1057 case ("clearDebugFlags",_)
1058 algorithm
1059 ✗ FlagsUtil.resetDebugFlags();
1060 then
1061 Values.BOOL(true);
1062
1063 case ("clearDebugFlags",_)
1064 then Values.BOOL(false);
1065
1066 case ("getConfigFlagValidOptions",{Values.STRING(str)})
1067 algorithm
1068 ✗ (strs1, str, strs2) := FlagsUtil.getValidOptionsAndDescription(str);
1069 ✗ then
1070 Values.TUPLE({
1071 ValuesMake.makeStringArray(strs1),
1072 Values.STRING(str),
1073 ValuesMake.makeStringArray(strs2)
1074 });
1075
1076 case ("getConfigFlagValidOptions",{Values.STRING(_)})
1077 ✗ then
1078 Values.TUPLE({
1079 ValuesMake.makeArray({}),
1080 Values.STRING(""),
1081 ValuesMake.makeArray({})
1082 });
1083
1084 case ("cd",{Values.STRING("")})
1085 21 then Values.STRING(System.pwd());
1086
1087 case ("cd",{Values.STRING(str)})
1088 algorithm
1089
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 0 := System.cd(str);
1090 1 then
1091 Values.STRING(System.pwd());
1092
1093 case ("cd",{Values.STRING(str)})
1094 algorithm
1095 ✗ false := System.directoryExists(str);
1096 ✗ res := stringAppendList({"Error, directory ",str," does not exist,"});
1097 ✗ then
1098 Values.STRING(res);
1099
1100 case ("mkdir",{Values.STRING(str)})
1101 algorithm
1102
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 true := System.directoryExists(str);
1103 then
1104 Values.BOOL(true);
1105
1106 case ("mkdir",{Values.STRING(str)})
1107
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 then Values.BOOL(Util.createDirectoryTree(str));
1108
1109 case ("copy",{Values.STRING(str1),Values.STRING(str2)})
1110
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 then Values.BOOL(System.copyFile(str1,str2));
1111
1112 case ("remove",{Values.STRING(str)})
1113
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 then Values.BOOL(System.removeDirectory(str));
1114
1115 case ("getVersion",{Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT("OpenModelica")))})
1116 ✗ then Values.STRING(Settings.getVersionNr());
1117
1118 case ("getVersion",{Values.CODE(Absyn.C_TYPENAME(path))})
1119 ✗ then Values.STRING(getPackageVersion(path,SymbolTable.getAbsyn()));
1120
1121 case ("getTempDirectoryPath",{})
1122 ✗ then Values.STRING(Settings.getTempDirectoryPath());
1123
1124 case ("system",{Values.STRING(str),Values.STRING(filename)})
1125 179 then Values.INTEGER(System.systemCall(str,filename));
1126
1127 case ("system_parallel",{Values.ARRAY(valueLst=vals),Values.INTEGER(i)})
1128 algorithm
1129 ✗ strs := List.map(vals, ValuesUtil.extractValueString);
1130 ✗ then
1131 ValuesMake.makeIntArray(System.systemCallParallel(strs,i));
1132
1133 case ("timerClear",{Values.INTEGER(i)})
1134 algorithm
1135 ✗ System.realtimeClear(i);
1136 then
1137 Values.NORETCALL();
1138
1139 case ("timerTick",{Values.INTEGER(i)})
1140 algorithm
1141 ✗ System.realtimeTick(i);
1142 then
1143 Values.NORETCALL();
1144
1145 case ("timerTock",{Values.INTEGER(i)})
1146 algorithm
1147 ✗ true := System.realtimeNtick(i) > 0;
1148 ✗ then
1149 Values.REAL(System.realtimeTock(i));
1150
1151 case ("timerTock",_)
1152 then Values.REAL(-1.0);
1153
1154 case ("timerAccumulated",{Values.INTEGER(i)})
1155 algorithm
1156 ✗ true := System.realtimeNtick(i) > 0;
1157 ✗ then
1158 Values.REAL(System.realtimeAccumulated(i));
1159
1160 case ("timerAccumulated",_)
1161 then Values.REAL(-1.0);
1162
1163 case ("readFile",{Values.STRING(str)})
1164 364 then Values.STRING(System.readFile(str));
1165
1166 case ("readFile",_)
1167 then Values.STRING("");
1168
1169 case ("writeFile",{Values.STRING(str),Values.STRING(str1),Values.BOOL(false)})
1170 algorithm
1171 32 System.writeFile(str,str1);
1172 then
1173 Values.BOOL(true);
1174
1175 case ("writeFile",{Values.STRING(str),Values.STRING(str1),Values.BOOL(true)})
1176 algorithm
1177 ✗ System.appendFile(str, str1);
1178 then
1179 Values.BOOL(true);
1180
1181 case ("writeFile",_)
1182 then Values.BOOL(false);
1183
1184 case ("deleteFile",{Values.STRING(str)})
1185
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 then Values.BOOL(System.removeFile(str) == 0);
1186
1187 case ("compareFiles",{Values.STRING(str1),Values.STRING(str2)})
1188
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 then Values.BOOL(System.fileContentsEqual(str1,str2));
1189
1190 case ("compareFilesAndMove",{Values.STRING(str1),Values.STRING(str2)})
1191 algorithm
1192 ✗ true := System.regularFileExists(str1);
1193 ✗ b := System.regularFileExists(str2) and System.fileContentsEqual(str1,str2);
1194 ✗ b := if not b then System.rename(str1,str2) else System.removeFile(str1) == 0;
1195 ✗ then
1196 Values.BOOL(b);
1197
1198 case ("compareFilesAndMove",_)
1199 then Values.BOOL(false);
1200
1201 case ("getErrorString",{Values.BOOL(b)})
1202 5382 then Values.STRING(Error.printMessagesStr(b));
1203
1204 case ("countMessages",_)
1205 ✗ then Values.TUPLE({
1206 Values.INTEGER(Error.getNumMessages()),
1207 Values.INTEGER(Error.getNumErrorMessages()),
1208 Values.INTEGER(ErrorExt.getNumWarningMessages())
1209 });
1210
1211 case ("clearMessages",{})
1212 algorithm
1213 ✗ Error.clearMessages();
1214 then
1215 Values.BOOL(true);
1216
1217 case ("getMessagesStringInternal",{Values.BOOL(true)})
1218 algorithm
1219 ✗ messages := List.unique(Error.getMessages());
1220 ✗ then
1221 ValuesMake.makeArray(List.map(messages, errorToValue));
1222
1223 case ("getMessagesStringInternal",{Values.BOOL(false)})
1224 ✗ then ValuesMake.makeArray(List.map(Error.getMessages(), errorToValue));
1225
1226 case ("stringTypeName",{Values.STRING(str)})
1227 ✗ then Values.CODE(Absyn.C_TYPENAME(Parser.stringPath(str)));
1228
1229 case ("stringVariableName",{Values.STRING(str)})
1230 4 then Values.CODE(Absyn.C_VARIABLENAME(Parser.stringCref(str)));
1231
1232 case ("typeNameString",{Values.CODE(A=Absyn.C_TYPENAME(path=path))})
1233 139 then Values.STRING(AbsynUtil.pathString(path));
1234
1235 case ("typeNameStrings",{Values.CODE(A=Absyn.C_TYPENAME(path=path))})
1236 ✗ then ValuesMake.makeArray(List.map(AbsynUtil.pathToStringList(path),ValuesMake.makeString));
1237
1238 case ("generateHeader",{Values.STRING(filename)})
1239 algorithm
1240 ✗ str := Tpl.tplString(Unparsing.programExternalHeader, SymbolTable.getSCode());
1241 ✗ System.writeFile(filename,str);
1242 then
1243 Values.BOOL(true);
1244
1245 case ("generateHeader",_)
1246 then Values.BOOL(false);
1247
1248 case ("generateJuliaHeader",{Values.STRING(filename)})
1249 algorithm
1250 ✗ str := Tpl.tplString(Unparsing.programExternalHeaderJulia, SymbolTable.getSCode());
1251 ✗ System.writeFile(filename,str);
1252 then
1253 Values.BOOL(true);
1254
1255 case ("generateJuliaHeader",_)
1256 then Values.BOOL(false);
1257
1258 case ("generateCode",{Values.CODE(Absyn.C_TYPENAME(path))})
1259 algorithm
1260
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 (outCache, Util.SUCCESS()) := Static.instantiateDaeFunction(outCache, env, path, false, NONE(), true);
1261 2 outCache := cevalGenerateFunction(outCache,env,SymbolTable.getAbsyn(),path);
1262 then
1263 Values.BOOL(true);
1264
1265 case ("generateCode",_)
1266 then Values.BOOL(false);
1267
1268 case ("getExternalFunctions",{Values.CODE(Absyn.C_TYPENAME(path))})
1269 algorithm
1270 1 (outCache, str) := getExternalFunctions(outCache, env, path);
1271 1 then
1272 Values.STRING(str);
1273
1274 case ("getExternalFunctions",_)
1275 then Values.STRING("");
1276
1277 case ("generateScriptingAPI",{Values.CODE(Absyn.C_TYPENAME(className)), Values.STRING(name)})
1278 algorithm
1279 ✗ sp := SymbolTable.getSCode();
1280 elts := match FBuiltin.getElementWithPathCheckBuiltin(sp, className)
1281 case SCode.CLASS(classDef=SCode.PARTS(elementLst=elts)) then elts;
1282 ✗ case cl algorithm Error.addSourceMessage(Error.INTERNAL_ERROR, {AbsynUtil.pathString(className) + " does not contain SCode.PARTS"}, SCodeUtil.elementInfo(cl)); then fail();
1283 end match;
1284 tys := {};
1285 ✗ for elt in elts loop
1286 () := matchcontinue elt
1287 case SCode.CLASS(partialPrefix=SCode.NOT_PARTIAL(), restriction=SCode.R_FUNCTION(SCode.FR_EXTERNAL_FUNCTION()))
1288 algorithm
1289 ✗ (outCache, ty, _) := Lookup.lookupType(outCache, env, AbsynUtil.suffixPath(className, elt.name), NONE() /*SOME(elt.info)*/);
1290 ✗ if isSimpleAPIFunction(ty) then
1291 ✗ tys := ty::tys;
1292 end if;
1293 then ();
1294 else ();
1295 end matchcontinue;
1296 end for;
1297 ✗ str1 := Tpl.tplString(GenerateAPIFunctionsTpl.getCevalScriptInterface, tys);
1298 ✗ str2 := Tpl.tplString3(GenerateAPIFunctionsTpl.getQtInterface, tys, name + "::", name);
1299 ✗ str3 := Tpl.tplString2(GenerateAPIFunctionsTpl.getQtInterfaceHeaders, tys, name);
1300 ✗ then
1301 Values.TUPLE({Values.BOOL(true),Values.STRING(str1),Values.STRING(str2),Values.STRING(str3)});
1302
1303 case ("generateScriptingAPI",_)
1304 then Values.TUPLE({Values.BOOL(false),Values.STRING(""),Values.STRING("")});
1305
1306 case ("generateEntryPoint",{Values.STRING(filename),Values.CODE(Absyn.C_TYPENAME(path)),Values.STRING(str)})
1307 algorithm
1308 ✗ str := Tpl.tplString2(CodegenCFunctions.generateEntryPoint, path, str);
1309 ✗ System.writeFile(filename,str);
1310 then
1311 Values.BOOL(true);
1312
1313 case ("generateEntryPoint", _)
1314 then Values.BOOL(false);
1315
1316 case ("checkInterfaceOfPackages",{Values.CODE(Absyn.C_TYPENAME(path)),Values.ARRAY(valueLst=vals)})
1317 algorithm
1318 ✗ sp := SymbolTable.getSCode();
1319 ✗ cl := SCodeUtil.getElementWithPath(sp,path);
1320 ✗ interfaceTypeAssoc := List.map1(vals, getInterfaceTypeAssocElt, SCodeUtil.elementInfo(cl));
1321 ✗ interfaceType := getInterfaceType(cl, interfaceTypeAssoc);
1322 ✗ List.map1_0(sp, verifyInterfaceType, interfaceType);
1323 then
1324 Values.BOOL(true);
1325
1326 case ("checkInterfaceOfPackages",_)
1327 then Values.BOOL(false);
1328
1329 case ("generateSeparateCodeDependenciesMakefile",_)
1330 ✗ then generateSeparateCodeDependenciesMakefile(args);
1331
1332 case ("generateSeparateCodeDependencies",_)
1333 ✗ then generateSeparateCodeDependencies(args);
1334
1335 case ("generateSeparateCode", _)
1336 algorithm
1337 ✗ (v, outCache) := generateSeparateCode(args, outCache, env);
1338 then
1339 v;
1340
1341 case ("getImportedNames",{Values.CODE(Absyn.C_TYPENAME(path))})
1342 algorithm
1343 ✗ (vals, cvars) := getImportedNames(ProgramUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn()));
1344 ✗ v := Values.TUPLE({ValuesMake.makeArray(vals),ValuesMake.makeArray(cvars)});
1345 then
1346 v;
1347
1348 case ("getImportedNames",_)
1349 ✗ then (Values.TUPLE({ValuesMake.makeArray({}),ValuesMake.makeArray({})}));
1350
1351 case ("getMMfileTotalDependencies",{Values.STRING(str1), Values.STRING(str2)})
1352 algorithm
1353 ✗ strs := getMMfileTotalDependencies(str1, str2);
1354 ✗ vals := list(Values.STRING(s) for s in strs);
1355 ✗ then
1356 ValuesMake.makeArray(vals);
1357
1358 case ("getMMfileTotalDependencies",_)
1359 ✗ then ValuesMake.makeArray({});
1360
1361 case ("loadModel",{Values.CODE(Absyn.C_TYPENAME(path)),Values.ARRAY(valueLst=cvars),Values.BOOL(b),Values.STRING(str),Values.BOOL(requireExactVersion)})
1362 algorithm
1363 421 p := SymbolTable.getAbsyn();
1364 421 execStatReset();
1365 421 pathstr := Settings.getModelicaPath(Testsuite.isRunning());
1366 421 strs := List.map(cvars, ValuesUtil.extractValueString);
1367 /* If the user requests a custom version to parse as, set it up */
1368 421 oldLanguageStd := Config.getLanguageStandard();
1369
2/4
✓ Branch 0 taken 421 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 421 times.
421 b1 := not stringEq(str,"");
1370 if b1 then
1371 ✗ Config.setLanguageStandard(Config.versionStringToStd(str));
1372 end if;
1373 842 (p,b) := loadModel({(path,"call to loadModel",strs,false)},pathstr,p,true,b,true,requireExactVersion,false);
1374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 421 times.
421 if b1 then
1375 ✗ Config.setLanguageStandard(oldLanguageStd);
1376 end if;
1377 421 Print.clearBuf();
1378 421 SymbolTable.setAbsyn(p);
1379
4/4
✓ Branch 0 taken 1464 times.
✓ Branch 1 taken 421 times.
✓ Branch 2 taken 1464 times.
✓ Branch 3 taken 421 times.
1885 CodegenWasmJitFunctions.precompilePrebuiltModules(PackageManagement.installMissingWasmOfLoaded(list(AbsynUtil.classFilename(c) for c in p.classes), CodegenWasmJitFunctions.prebuiltExternalsABI()));
1380 421 execStat("loadModel("+AbsynUtil.pathString(path)+")");
1381 421 outCache := FCore.emptyCache();
1382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 421 times.
421 then
1383 Values.BOOL(b);
1384
1385 case ("loadModel",Values.CODE(Absyn.C_TYPENAME(path))::_)
1386 algorithm
1387 ✗ pathstr := AbsynUtil.pathString(path);
1388 ✗ Error.addMessage(Error.LOAD_MODEL_ERROR, {pathstr});
1389 then
1390 Values.BOOL(false);
1391
1392 case ("loadFile",Values.STRING(name)::Values.STRING(encoding)::Values.BOOL(b)::Values.BOOL(b1)::Values.BOOL(requireExactVersion)::Values.BOOL(allowWithin)::_)
1393 algorithm
1394 739 execStatReset();
1395 739 name := Testsuite.friendlyPath(name);
1396 739 newp := loadFile(name, encoding, SymbolTable.getAbsyn(), b, b1, requireExactVersion, allowWithin);
1397 737 execStat("loadFile("+name+")");
1398 737 SymbolTable.setAbsyn(newp);
1399 737 outCache := FCore.emptyCache();
1400 then
1401 Values.BOOL(true);
1402
1403 case ("loadFile",_)
1404 then Values.BOOL(false);
1405
1406 case ("loadFiles",Values.ARRAY(valueLst=vals)::Values.STRING(encoding)::Values.INTEGER(i)::Values.BOOL(b)::Values.BOOL(b1)::Values.BOOL(requireExactVersion)::Values.BOOL(allowWithin)::_)
1407 algorithm
1408 4 strs := List.mapMap(vals,ValuesUtil.extractValueString,Testsuite.friendlyPath);
1409 4 newps := Parser.parallelParseFilesToProgramList(strs,encoding,numThreads=i);
1410 4 newp := SymbolTable.getAbsyn();
1411
2/2
✓ Branch 0 taken 756 times.
✓ Branch 1 taken 4 times.
760 for p in newps loop
1412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 str :: strs := strs;
1413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 if not allowWithin then
1414 ✗ checkTopClassWithin(p, str);
1415 end if;
1416 756 newp := checkUsesAndUpdateProgram(p, newp, b, Settings.getModelicaPath(Testsuite.isRunning()), b1, requireExactVersion, false);
1417 end for;
1418 4 SymbolTable.setAbsyn(newp);
1419 4 outCache := FCore.emptyCache();
1420 then
1421 Values.BOOL(true);
1422
1423 case ("loadFiles",_)
1424 algorithm
1425 // System.GC_enable();
1426 then Values.BOOL(false);
1427
1428 case ("parseEncryptedPackage",Values.STRING(filename)::Values.STRING(workdir)::_)
1429 algorithm
1430 2 vals := {}; // make sure is initialized, see #9250
1431 2 str := System.pwd();
1432 try
1433 2 filename := System.realpath(filename);
1434
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 0 := System.cd(System.dirname(filename));
1435 2 (b, filename) := unZipEncryptedPackageAndCheckFile(workdir, filename, false);
1436
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if b then
1437 // clear the errors before!
1438 2 Error.clearMessages() "Clear messages";
1439 2 Print.clearErrorBuf() "Clear error buffer";
1440 2 filename := Testsuite.friendlyPath(filename);
1441 2 paths := Interactive.parseFile(filename, "UTF-8");
1442 2 vals := List.map(paths,ValuesMake.makeCodeTypeName);
1443 end if;
1444 else
1445 ✗ b := false;
1446 end try;
1447
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 0 := System.cd(str);
1448 2 then
1449 ValuesMake.makeArray(vals);
1450
1451 case ("parseEncryptedPackage",_)
1452 ✗ then
1453 ValuesMake.makeArray({});
1454
1455 case ("loadEncryptedPackage",Values.STRING(filename)::Values.STRING(workdir)::Values.BOOL(bval)::Values.BOOL(b)::Values.BOOL(b1)::Values.BOOL(requireExactVersion)::_)
1456 algorithm
1457 2 str := System.pwd();
1458 try
1459 2 filename := System.realpath(filename);
1460
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 0 := System.cd(System.dirname(filename));
1461 2 (b, filename) := unZipEncryptedPackageAndCheckFile(workdir, filename, bval);
1462
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (b) then
1463 2 execStatReset();
1464 2 filename := Testsuite.friendlyPath(filename);
1465 2 p := SymbolTable.getAbsyn();
1466 2 newp := loadFile(filename, "UTF-8", p, b, b1, requireExactVersion);
1467 2 execStat("loadFile("+filename+")");
1468 2 SymbolTable.setAbsyn(newp);
1469 end if;
1470 2 outCache := FCore.emptyCache();
1471 else
1472 ✗ b := false;
1473 end try;
1474
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 0 := System.cd(str);
1475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 then
1476 Values.BOOL(b);
1477
1478 case ("loadEncryptedPackage",_)
1479 then Values.BOOL(false);
1480
1481 case ("alarm",{Values.INTEGER(i)})
1482 139 then Values.INTEGER(System.alarm(i));
1483
1484 15 case ("getClassNames", _) then getClassNames(args);
1485
1486 case ("reloadClass",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.STRING(encoding)})
1487 algorithm
1488 ✗ Absyn.CLASS(info=SOURCEINFO(fileName=filename,lastModification=r2)) :=
1489 ProgramUtil.getPathedClassInProgram(classpath, SymbolTable.getAbsyn());
1490 ✗ (true,_,r1,_) := System.stat(filename);
1491 ✗ if not realEq(r1, r2) then
1492 ✗ reloadClass(filename, encoding);
1493 end if;
1494 then
1495 Values.BOOL(true);
1496
1497 case ("reloadClass",{Values.CODE(Absyn.C_TYPENAME(classpath)),_})
1498 algorithm
1499 ✗ failure(ProgramUtil.getPathedClassInProgram(classpath, SymbolTable.getAbsyn()));
1500 ✗ Error.addMessage(Error.LOAD_MODEL_ERROR, {AbsynUtil.pathString(classpath)});
1501 then
1502 Values.BOOL(false);
1503
1504 case ("reloadClass",_)
1505 then Values.BOOL(false);
1506
1507 case ("loadString",Values.STRING(str)::Values.STRING(name)::Values.STRING(encoding)::Values.BOOL(mergeAST)::Values.BOOL(b)::Values.BOOL(b1)::Values.BOOL(requireExactVersion)::_)
1508 algorithm
1509
2/4
✓ Branch 0 taken 762 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 762 times.
762 str := if not (encoding == "UTF-8") then System.iconv(str, encoding, "UTF-8") else str;
1510 762 parsed := Parser.parsestring(str,name);
1511 762 newp := checkUsesAndUpdateProgram(parsed, SymbolTable.getAbsyn(), b,
1512 Settings.getModelicaPath(Testsuite.isRunning()), b1, requireExactVersion, mergeAST);
1513 762 SymbolTable.setAbsynLoaded(newp, parsed);
1514 762 outCache := FCore.emptyCache();
1515 then
1516 Values.BOOL(true);
1517
1518 case ("loadString",_) then Values.BOOL(false);
1519
1520 case ("help",{Values.STRING("")})
1521 ✗ then Values.STRING(FlagsUtil.printUsage());
1522
1523 case ("help",{Values.STRING(str)})
1524 ✗ then Values.STRING(FlagsUtil.printHelp({str}));
1525
1526 case ("getTimeStamp",{Values.CODE(Absyn.C_TYPENAME(classpath))})
1527 algorithm
1528 ✗ Absyn.CLASS(info=SOURCEINFO(lastModification=r)) :=
1529 ProgramUtil.getPathedClassInProgram(classpath,SymbolTable.getAbsyn());
1530 ✗ str := System.ctime(r);
1531 ✗ then
1532 Values.TUPLE({Values.REAL(r),Values.STRING(str)});
1533
1534 case ("getTimeStamp",_)
1535 then Values.TUPLE({Values.REAL(0.0),Values.STRING("")});
1536
1537 case ("getClassRestriction",{Values.CODE(Absyn.C_TYPENAME(classpath))})
1538 algorithm
1539 ✗ str := Interactive.getClassRestriction(classpath, SymbolTable.getAbsyn());
1540 ✗ then
1541 Values.STRING(str);
1542
1543 case ("classAnnotationExists",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.CODE(Absyn.C_TYPENAME(path))})
1544 algorithm
1545 ✗ b := ProgramUtil.getNamedAnnotationExp(classpath, SymbolTable.getAbsyn(), path, SOME(false), isSome);
1546 ✗ then
1547 Values.BOOL(b);
1548
1549 case ("getBooleanClassAnnotation",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.CODE(Absyn.C_TYPENAME(path))})
1550 algorithm
1551 ✗ Absyn.BOOL(b) := ProgramUtil.getNamedAnnotationExp(classpath, SymbolTable.getAbsyn(), path, NONE(), Interactive.getAnnotationExp);
1552 ✗ then
1553 Values.BOOL(b);
1554
1555 case ("getBooleanClassAnnotation",{Values.CODE(Absyn.C_TYPENAME(classpath)),Values.CODE(Absyn.C_TYPENAME(path))})
1556 algorithm
1557 ✗ Error.addMessage(Error.CLASS_ANNOTATION_DOES_NOT_EXIST,
1558 {AbsynUtil.pathString(path), AbsynUtil.pathString(classpath)});
1559 ✗ then
1560 fail();
1561
1562 case ("strtok",{Values.STRING(str),Values.STRING(token)})
1563 algorithm
1564 ✗ strs := System.strtok(str, token);
1565 ✗ then
1566 ValuesMake.makeStringArray(strs);
1567
1568 case ("stringSplit",{Values.STRING(str),Values.STRING(token)})
1569 algorithm
1570 ✗ strs := Util.stringSplitAtChar(str, token);
1571 ✗ then
1572 ValuesMake.makeStringArray(strs);
1573
1574 case ("stringReplace",{Values.STRING(str1),Values.STRING(str2),Values.STRING(str3)})
1575 algorithm
1576 4105 str := System.stringReplace(str1, str2, str3);
1577 4105 then
1578 Values.STRING(str);
1579
1580 /* Checks the installation of OpenModelica and tries to find common errors */
1581 ✗ case ("checkSettings",{}) then checkSettings();
1582
1583 case ("echo",{v as Values.BOOL(bval)})
1584 algorithm
1585
2/2
✓ Branch 0 taken 358 times.
✓ Branch 1 taken 349 times.
1065 Settings.setEcho(if bval then 1 else 0);
1586 707 then
1587 v;
1588
1589 case ("numProcessors",{})
1590 15 then Values.INTEGER(Config.noProc());
1591
1592 case ("runScript",{Values.STRING(str)})
1593 algorithm
1594 289 str := Testsuite.friendlyPath(str);
1595 289 res := Interactive.evaluate(Parser.parseexp(str), true);
1596 289 then
1597 Values.STRING(res);
1598
1599 case ("runScript",_)
1600 then Values.STRING("Failed");
1601
1602 case ("exit",{Values.INTEGER(i)})
1603 algorithm
1604 ✗ System.exit(i);
1605 /* Cannot reach here */
1606 ✗ then
1607 fail();
1608
1609 case ("getMemorySize",{})
1610 ✗ then Values.REAL(System.getMemorySize());
1611
1612 case ("getAllSubtypeOf",{
1613 Values.CODE(Absyn.C_TYPENAME(path)),
1614 Values.CODE(Absyn.C_TYPENAME(parentClass)),
1615 _, // qualified not used
1616 Values.BOOL(includePartial),
1617 Values.BOOL(sort)})
1618 algorithm
1619 5 paths := InteractiveUtil.getAllSubtypeOf(path, parentClass, SymbolTable.getAbsyn(), includePartial, sort);
1620 5 then
1621 ValuesMake.makeCodeTypeNameArray(paths);
1622
1623 case ("getReplaceableChoices", {
1624 Values.CODE(Absyn.C_TYPENAME(path)),
1625 Values.CODE(Absyn.C_TYPENAME(parentClass)),
1626 Values.BOOL(includePartial),
1627 Values.BOOL(sort)})
1628 1 then InteractiveUtil.getReplaceableChoices(path, parentClass, SymbolTable.getAbsyn(), includePartial, sort);
1629
1630 // check for OMSimulator API calls
1631 case (_,_)
1632 6861 then CevalScriptOMSimulator.ceval(functionName, args);
1633
1634 else
1635 algorithm
1636 6796 (outCache,v) := CevalScriptBackend.cevalInteractiveFunctions3(outCache,env,functionName,args,msg);
1637 5774 then
1638 v;
1639
1640 end matchcontinue;
1641 end cevalInteractiveFunctions2;
1642
1643 public function evalCodeTypeName
1644 input Values.Value val;
1645 input FCore.Graph env;
1646 output Values.Value res;
1647 algorithm
1648 res := matchcontinue val
1649 local
1650 Absyn.Path path;
1651 case Values.CODE(Absyn.C_TYPENAME(path as Absyn.IDENT(_) /* We only want to lookup idents in the symboltable; also speeds up e.g. simulate(Modelica.A.B.C) so we do not instantiate all classes */))
1652 algorithm
1653
0/6
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
2503 (_,_,_,DAE.VALBOUND(valBound=res as Values.CODE(A=Absyn.C_TYPENAME())),_,_,_,_,_) := Lookup.lookupVar(FCore.emptyCache(), env, ComponentReference.pathToCref(path));
1654 then res;
1655 else val;
1656 end matchcontinue;
1657 end evalCodeTypeName;
1658
1659 protected function getVariableNames
1660 input list<InteractiveTypes.Variable> vars;
1661 input list<Values.Value> acc;
1662 output list<Values.Value> ovars;
1663 algorithm
1664 ovars := match vars
1665 local
1666 list<InteractiveTypes.Variable> vs;
1667 String p;
1668 ✗ case {} then listReverse(acc);
1669 case InteractiveTypes.IVAR(varIdent = "$echo") :: vs
1670 ✗ then getVariableNames(vs,acc);
1671 case InteractiveTypes.IVAR(varIdent = p) :: vs
1672 ✗ then getVariableNames(vs,Values.CODE(Absyn.C_VARIABLENAME(Absyn.CREF_IDENT(p,{})))::acc);
1673 end match;
1674 end getVariableNames;
1675
1676 public function getPackageVersion
1677 input Absyn.Path path;
1678 input Absyn.Program p;
1679 output String version = "";
1680 protected
1681 Boolean evalParamAnn;
1682 algorithm
1683 213 evalParamAnn := Config.getEvaluateParametersInAnnotations();
1684 213 Config.setEvaluateParametersInAnnotations(true);
1685 try
1686
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 213 times.
213 Absyn.STRING(version) := ProgramUtil.getNamedAnnotationExp(path, p, Absyn.IDENT("version"), SOME(Absyn.STRING("")), Interactive.getAnnotationExp);
1687 else
1688 version := "";
1689 end try;
1690 213 Config.setEvaluateParametersInAnnotations(evalParamAnn);
1691 end getPackageVersion;
1692
1693 protected function errorToValue
1694 input ErrorTypes.TotalMessage err;
1695 output Values.Value val;
1696 algorithm
1697 val := match err
1698 local
1699 Absyn.Path msgpath;
1700 Values.Value tyVal,severityVal,infoVal;
1701 list<Values.Value> values;
1702 String message;
1703 String msg_str;
1704 Integer id;
1705 ErrorTypes.Severity severity;
1706 ErrorTypes.MessageType ty;
1707 SourceInfo info;
1708 case ErrorTypes.TOTALMESSAGE(ErrorTypes.MESSAGE(id,ty,severity,message),info)
1709 algorithm
1710 msg_str := message;
1711 msgpath := Absyn.FULLYQUALIFIED(Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("Scripting",Absyn.IDENT("ErrorMessage"))));
1712 ✗ tyVal := errorTypeToValue(ty);
1713 ✗ severityVal := errorLevelToValue(severity);
1714 ✗ infoVal := infoToValue(info);
1715 ✗ values := {infoVal,Values.STRING(msg_str),tyVal,severityVal,Values.INTEGER(id)};
1716 ✗ then Values.RECORD(msgpath,values,{"info","message","kind","level","id"},-1);
1717 end match;
1718 end errorToValue;
1719
1720 protected function infoToValue
1721 input SourceInfo info;
1722 output Values.Value val;
1723 algorithm
1724 val := match info
1725 local
1726 list<Values.Value> values;
1727 Absyn.Path infopath;
1728 Integer ls,cs,le,ce;
1729 String filename;
1730 Boolean readonly;
1731 case SOURCEINFO(filename,readonly,ls,cs,le,ce,_)
1732 algorithm
1733 infopath := Absyn.FULLYQUALIFIED(Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("Scripting",Absyn.IDENT("SourceInfo"))));
1734 ✗ values := {Values.STRING(filename),Values.BOOL(readonly),Values.INTEGER(ls),Values.INTEGER(cs),Values.INTEGER(le),Values.INTEGER(ce)};
1735 ✗ then Values.RECORD(infopath,values,{"filename","readonly","lineStart","columnStart","lineEnd","columnEnd"},-1);
1736 end match;
1737 end infoToValue;
1738
1739 protected function makeErrorEnumLiteral
1740 input String enumName;
1741 input String enumField;
1742 input Integer index;
1743 output Values.Value val;
1744 annotation(__OpenModelica_EarlyInline=true);
1745 algorithm
1746 ✗ val := Values.ENUM_LITERAL(Absyn.FULLYQUALIFIED(Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("Scripting",Absyn.QUALIFIED(enumName,Absyn.IDENT(enumField))))),index);
1747 end makeErrorEnumLiteral;
1748
1749 protected function errorTypeToValue
1750 input ErrorTypes.MessageType ty;
1751 output Values.Value val;
1752 algorithm
1753 val := match ty
1754 ✗ case ErrorTypes.SYNTAX() then makeErrorEnumLiteral("ErrorKind","syntax",1);
1755 ✗ case ErrorTypes.GRAMMAR() then makeErrorEnumLiteral("ErrorKind","grammar",2);
1756 ✗ case ErrorTypes.TRANSLATION() then makeErrorEnumLiteral("ErrorKind","translation",3);
1757 ✗ case ErrorTypes.SYMBOLIC() then makeErrorEnumLiteral("ErrorKind","symbolic",4);
1758 ✗ case ErrorTypes.SIMULATION() then makeErrorEnumLiteral("ErrorKind","runtime",5);
1759 ✗ case ErrorTypes.SCRIPTING() then makeErrorEnumLiteral("ErrorKind","scripting",6);
1760 else
1761 algorithm
1762 ✗ print("errorTypeToValue failed\n");
1763 ✗ then fail();
1764 end match;
1765 end errorTypeToValue;
1766
1767 protected function errorLevelToValue
1768 input ErrorTypes.Severity severity;
1769 output Values.Value val;
1770 algorithm
1771 val := match severity
1772 ✗ case ErrorTypes.INTERNAL() then makeErrorEnumLiteral("ErrorLevel","internal",1);
1773 ✗ case ErrorTypes.ERROR() then makeErrorEnumLiteral("ErrorLevel","error",2);
1774 ✗ case ErrorTypes.WARNING() then makeErrorEnumLiteral("ErrorLevel","warning",3);
1775 ✗ case ErrorTypes.NOTIFICATION() then makeErrorEnumLiteral("ErrorLevel","notification",4);
1776 else
1777 algorithm
1778 ✗ print("errorLevelToValue failed\n");
1779 ✗ then fail();
1780 end match;
1781 end errorLevelToValue;
1782
1783 protected function generateFunctionName
1784 "@author adrpo:
1785 generate the function name from a path."
1786 input Absyn.Path functionPath;
1787 output String functionName;
1788 algorithm
1789 142 functionName := AbsynUtil.pathStringUnquoteReplaceDot(functionPath, "_");
1790 end generateFunctionName;
1791
1792 protected function generateFunctionFileName
1793 "@author adrpo:
1794 generate the function name from a path."
1795 input Absyn.Path functionPath;
1796 output String functionName;
1797 protected
1798 String n1, n2;
1799 algorithm
1800 148 functionName := AbsynUtil.pathStringUnquoteReplaceDot(functionPath, "_");
1801
1802
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 1 time.
148 if stringLength(functionName) > Global.maxFunctionFileLength then
1803 1 n1 := AbsynUtil.pathFirstIdent(functionPath);
1804 1 n2 := AbsynUtil.pathLastIdent(functionPath);
1805 1 functionName := System.unquoteIdentifier(n1 + "_" + n2);
1806 1 functionName := functionName + "_" + intString(tick());
1807 end if;
1808 end generateFunctionFileName;
1809
1810 public function getFunctionDependencies
1811 "returns all function dependencies as paths, also the main function and the function tree"
1812 input FCore.Cache cache;
1813 input Absyn.Path functionName;
1814 output DAE.Function mainFunction "the main function";
1815 output list<Absyn.Path> dependencies "the dependencies as paths";
1816 output AvlTreePathFunction.Tree funcs "the function tree";
1817 algorithm
1818 170 funcs := FCore.getFunctionTree(cache);
1819 // First check if the main function exists... If it does not it might be an interactive function...
1820 170 mainFunction := DAEUtil.getNamedFunction(functionName, funcs);
1821 152 dependencies := SimCodeFunctionUtil.getCalledFunctionsInFunction(functionName,funcs);
1822 end getFunctionDependencies;
1823
1824 public function collectDependencies
1825 "collects all function dependencies, also the main function, uniontypes, metarecords"
1826 input FCore.Cache inCache;
1827 input FCore.Graph env;
1828 input Absyn.Path functionName;
1829 output FCore.Cache outCache;
1830 output DAE.Function mainFunction;
1831 output list<DAE.Function> dependencies;
1832 output list<DAE.Type> metarecordTypes;
1833 protected
1834 list<Absyn.Path> uniontypePaths,paths;
1835 AvlTreePathFunction.Tree funcs;
1836 algorithm
1837 170 (mainFunction, paths, funcs) := getFunctionDependencies(inCache, functionName);
1838 // The list of functions is not ordered, so we need to filter out the main function...
1839 148 dependencies := List.map1(paths, DAEUtil.getNamedFunction, funcs);
1840 148 dependencies := List.setDifference(dependencies, {mainFunction});
1841 148 uniontypePaths := DAEUtil.getUniontypePaths(dependencies,{});
1842 148 (outCache,metarecordTypes) := Lookup.lookupMetarecordsRecursive(inCache, env, uniontypePaths);
1843 end collectDependencies;
1844
1845 public function cevalGenerateFunction "Generates code for a given function name."
1846 input FCore.Cache inCache;
1847 input FCore.Graph inEnv;
1848 input Absyn.Program program;
1849 input Absyn.Path inPath;
1850 output FCore.Cache outCache;
1851 output String functionName;
1852 output String functionFileName;
1853 algorithm
1854 (outCache,functionName,functionFileName) := matchcontinue (inCache, inEnv, inPath)
1855 local
1856 String pathstr, fileName;
1857 FCore.Graph env;
1858 Absyn.Path path;
1859 FCore.Cache cache;
1860 DAE.Function mainFunction;
1861 list<DAE.Function> dependencies;
1862 list<DAE.Type> metarecordTypes;
1863 AvlTreePathFunction.Tree funcs;
1864 // template based translation
1865 case (cache, env, path) guard Flags.isSet(Flags.GEN) and (not Flags.isSet(Flags.GENERATE_CODE_CHEAT))
1866 algorithm
1867 164 (cache, mainFunction, dependencies, metarecordTypes) := collectDependencies(cache, env, path);
1868 142 pathstr := generateFunctionName(path);
1869 142 fileName := generateFunctionFileName(path);
1870 142 translateFunctions(program, fileName, SOME(mainFunction), dependencies, metarecordTypes, {});
1871 // The wasm-jit target produces a WebAssembly module that is JIT-compiled
1872 // in-process; there is no C source to compile into a shared object.
1873
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 142 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
142 if Config.simCodeTarget() <> "wasm-jit" then
1874 142 compileModel(fileName, {});
1875 end if;
1876 then
1877 (cache, pathstr, fileName);
1878 // Cheat if we want to generate code for Main.main
1879 // * Don't do dependency analysis of what functions to generate; just generate all of them
1880 // * Don't generate extra code for unreferenced MetaRecord types (for external functions)
1881 // This could be an annotation instead anyway.
1882 // * Don't compile the generated files
1883 case (cache, _, path) guard Flags.isSet(Flags.GEN) and Flags.isSet(Flags.GENERATE_CODE_CHEAT)
1884 algorithm
1885 ✗ funcs := FCore.getFunctionTree(cache);
1886 // First check if the main function exists... If it does not it might be an interactive function...
1887 ✗ pathstr := generateFunctionName(path);
1888 ✗ fileName := generateFunctionFileName(path);
1889 // The list of functions is not ordered, so we need to filter out the main function...
1890 ✗ dependencies := DAEUtil.getFunctionList(funcs);
1891 ✗ translateFunctions(program, fileName, NONE(), dependencies, {}, {});
1892 then
1893 (cache, pathstr, fileName);
1894 case (cache, env, path) guard Flags.isSet(Flags.GEN) and Flags.isSet(Flags.FAILTRACE)
1895 algorithm
1896 ✗ (cache,false) := Static.isExternalObjectFunction(cache,env,path);
1897 ✗ pathstr := generateFunctionName(path);
1898 ✗ fileName := generateFunctionFileName(path);
1899 ✗ Debug.trace("CevalScript.cevalGenerateFunction failed:\nfunction: " + pathstr + "\nfile: " + fileName + "\n");
1900 ✗ then
1901 fail();
1902 end matchcontinue;
1903 end cevalGenerateFunction;
1904
1905 protected function getExternalFunctions
1906 "Describes every external \"C\" function in a library as JSON, for the
1907 package manager that builds wasm modules for them."
1908 input FCore.Cache inCache;
1909 input FCore.Graph env;
1910 input Absyn.Path className;
1911 output FCore.Cache cache = inCache;
1912 output String json = "";
1913 protected
1914 Absyn.Program program = SymbolTable.getAbsyn();
1915 list<Absyn.Path> paths, fnPaths;
1916 list<SimCodeFunction.FunctionCode> fnCodes = {};
1917 SimCodeFunction.FunctionCode fnCode;
1918 SCode.Element cl;
1919 FCore.Graph cenv;
1920 algorithm
1921 try
1922 1 paths := externalCFunctionPaths(className, ProgramUtil.getPathedClassInProgram(className, program), {});
1923 else
1924 ✗ Error.addMessage(Error.LOOKUP_ERROR, {AbsynUtil.pathString(className), "<TOP>"});
1925 ✗ return;
1926 end try;
1927 1 setGlobalRoot(Global.optionSimCode, NONE());
1928
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 time.
6 for path in listReverse(paths) loop
1929 5 ErrorExt.setCheckpoint(getInstanceName());
1930 try
1931 5 (cache, cl, cenv) := Lookup.lookupClass(cache, env, path);
1932
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 4 times.
5 if SCodeUtil.classIsExternalObject(cl) then
1933 // As instantiating a component of the class does: the constructor and
1934 // destructor only instantiate inside its scope.
1935 1 cenv := FGraph.openScope(cenv, SCode.NOT_ENCAPSULATED(), SCodeUtil.className(cl), FGraph.restrictionToScopeType(SCodeUtil.getClassRestriction(cl)));
1936 1 (cache) := InstFunction.instantiateExternalObject(cache, cenv, InnerOuter.emptyInstHierarchy, SCodeUtil.getClassElements(cl), DAE.NOMOD(), false, SCode.noComment, SCodeUtil.elementInfo(cl));
1937 2 fnPaths := {AbsynUtil.suffixPath(path, "constructor"), AbsynUtil.suffixPath(path, "destructor")};
1938 else
1939
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 (cache, Util.SUCCESS()) := Static.instantiateDaeFunction(cache, env, path, false, NONE(), true);
1940 fnPaths := {path};
1941 end if;
1942
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 for fnPath in fnPaths loop
1943 6 (cache, fnCode) := elaborateFunctionCode(cache, env, program, fnPath);
1944 6 fnCodes := fnCode :: fnCodes;
1945 end for;
1946 5 ErrorExt.delCheckpoint(getInstanceName());
1947 else
1948 ✗ ErrorExt.rollBack(getInstanceName());
1949 ✗ Error.addCompilerWarning("getExternalFunctions: skipping " + AbsynUtil.pathString(path) + ", which does not instantiate on its own.");
1950 end try;
1951 end for;
1952 1 json := describeExternalFunctions(listReverse(fnCodes));
1953 end getExternalFunctions;
1954
1955 constant Integer prebuiltExternalsABI = 2
1956 "The interface of the call wrappers built from what getExternalFunctions
1957 describes: the index keys the modules by it.";
1958
1959 protected function describeExternalFunctions
1960 "The external \"C\" functions of `fnCodes` as JSON: each one's C name and the C
1961 types of its call in the specification's mapping, as the wasm-jit target
1962 declares the call, its Include annotations and include directories. One the
1963 wasm-jit target cannot call carries why instead."
1964 input list<SimCodeFunction.FunctionCode> fnCodes;
1965 output String json;
1966 protected
1967 list<JSON> functions = {};
1968 list<tuple<String, JSON>> entry;
1969 JSON dirsJSON, includesJSON, pathJSON;
1970 list<String> params, includes, dirs;
1971 String ret, extName, language;
1972 Absyn.Path name;
1973 SimCodeFunction.Function f;
1974 algorithm
1975
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 time.
7 for fc in fnCodes loop
1976 _ := match fc
1977 case SimCodeFunction.FUNCTIONCODE(mainFunction = SOME(f as SimCodeFunction.EXTERNAL_FUNCTION(
1978 name = name, extName = extName, includes = includes, language = language)),
1979 makefileParams = SimCodeFunction.MAKEFILE_PARAMS(includes = dirs))
1980 guard not externalServedByOmc(f)
1981 algorithm
1982
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
12 dirsJSON := JSON.makeList(list(JSON.makeString(includeDirectory(d)) for d in dirs));
1983
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
12 includesJSON := JSON.makeList(list(JSON.makeString(i) for i in includes));
1984 6 pathJSON := JSON.makeString(AbsynUtil.pathString(AbsynUtil.makeNotFullyQualified(name)));
1985 try
1986 6 (params, ret) := externalCSignature(f);
1987
8/12
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 12 taken 4 times.
✓ Branch 13 taken 6 times.
✓ Branch 14 taken 4 times.
✓ Branch 15 taken 6 times.
✓ Branch 20 taken 2 times.
✓ Branch 21 taken 4 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 2 times.
10 entry := {
1988 ("declare", JSON.makeBoolean(listEmpty(includes))),
1989 ("includeDirectories", dirsJSON),
1990 ("includes", includesJSON),
1991 ("name", JSON.makeString(if language == "FORTRAN 77" then extName + "_" else extName)),
1992 ("parameters", JSON.makeList(list(JSON.makeString(p) for p in params))),
1993 ("path", pathJSON),
1994 ("returns", if ret == "record" then JSON.makeNull() else JSON.makeString(ret))};
1995 else
1996 ✗ entry := {
1997 ("includeDirectories", dirsJSON),
1998 ("includes", includesJSON),
1999 ("path", pathJSON),
2000 ("unsupported", JSON.makeString(externalUnsupported(f)))};
2001 end try;
2002 // toString writes the pairs last to first.
2003 6 functions := JSON.LIST_OBJECT(listReverse(entry)) :: functions;
2004 then ();
2005 else ();
2006 end match;
2007 end for;
2008 2 json := JSON.toString(JSON.LIST_OBJECT({("functions", JSON.makeList(listReverse(functions))),
2009 ("abi", JSON.makeInteger(prebuiltExternalsABI))}));
2010 end describeExternalFunctions;
2011
2012 protected function includeDirectory
2013 "A directory from the -I flags of a function's makefile parameters."
2014 input String flag;
2015 output String dir;
2016 algorithm
2017 6 dir := System.trim(flag, "\"");
2018
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if StringUtil.startsWith(dir, "-I") then
2019 6 dir := System.trim(substring(dir, 3, stringLength(dir)), "\"");
2020 end if;
2021 end includeDirectory;
2022
2023 protected function externalScalarType
2024 "The C type a Modelica type maps to in an external call, as the wasm-jit
2025 target declares it: \"record\" for a record, which passes by pointer, and an
2026 array's element type. Fails for a type it cannot pass."
2027 input DAE.Type ty;
2028 output String cty;
2029 output Boolean isArray;
2030 algorithm
2031 (cty, isArray) := match ty
2032 case DAE.T_INTEGER() then ("int", false);
2033 case DAE.T_BOOL() then ("int", false);
2034 case DAE.T_ENUMERATION() then ("int", false);
2035 case DAE.T_REAL() then ("double", false);
2036 case DAE.T_STRING() then ("const char*", false);
2037 case DAE.T_COMPLEX(complexClassType = ClassInf.EXTERNAL_OBJ()) then ("void*", false);
2038 case DAE.T_COMPLEX(complexClassType = ClassInf.RECORD())
2039 guard List.all(ty.varLst, recordFieldPasses)
2040 then ("record", false);
2041 case DAE.T_ARRAY()
2042 algorithm
2043 ✗ (cty, _) := externalScalarType(ty.ty);
2044 ✗ if cty == "record" then
2045 ✗ fail();
2046 end if;
2047 then (cty, true);
2048 end match;
2049 end externalScalarType;
2050
2051 protected function recordFieldPasses
2052 "Whether the host can convert a record field: a scalar, a String, an array or
2053 a record of those."
2054 input DAE.Var field;
2055 output Boolean b;
2056 protected
2057 String cty;
2058 Boolean isArray;
2059 algorithm
2060 try
2061 ✗ (cty, isArray) := externalScalarType(field.ty);
2062 ✗ b := isArray or cty <> "void*";
2063 else
2064 b := match field.ty case DAE.T_ARRAY() then true; else false; end match;
2065 end try;
2066 end recordFieldPasses;
2067
2068 protected function variablePasses
2069 input SimCodeFunction.Variable v;
2070 output Boolean b;
2071 protected
2072 DAE.Type ty;
2073 algorithm
2074 b := match v
2075 case SimCodeFunction.VARIABLE(ty = ty)
2076 algorithm
2077 try
2078 9 (_, _) := externalScalarType(ty);
2079 b := true;
2080 else
2081 b := match ty case DAE.T_ARRAY() then true; else false; end match;
2082 end try;
2083 then b;
2084 else false;
2085 end match;
2086 end variablePasses;
2087
2088 protected function externalServedByOmc
2089 "Whether the wasm-jit target calls this in its own runtime: the string length
2090 and substring functions and scalar math, called with inputs only and
2091 returning the one output."
2092 input SimCodeFunction.Function f;
2093 output Boolean b = false;
2094 protected
2095 list<String> ins, outs;
2096 list<SimCodeFunction.Variable> funArgs, outVars;
2097 list<SimCodeFunction.SimExtArg> extArgs;
2098 String extName;
2099 algorithm
2100 _ := match f
2101 case SimCodeFunction.EXTERNAL_FUNCTION(extName = extName, funArgs = funArgs, extArgs = extArgs,
2102 outVars = outVars as {_}, extReturn = SimCodeFunction.SIMEXTARG())
2103 guard List.all(extArgs, externalArgIsInput)
2104 algorithm
2105 try
2106
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 5 times.
8 ins := list(variableCType(v) for v in funArgs);
2107
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 5 times.
10 outs := list(variableCType(v) for v in outVars);
2108 else
2109 ✗ return;
2110 end try;
2111 b := match (extName, ins, outs)
2112 case ("ModelicaStrings_length", {"const char*"}, {"int"}) then true;
2113 case ("ModelicaStrings_substring", {"const char*", "int", "int"}, {"const char*"}) then true;
2114
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
5 else listMember(extName, {"pow", "atan2", "sin", "cos", "tan", "asin", "acos", "atan", "sinh",
2115 "cosh", "tanh", "exp", "log", "log10", "cbrt", "expm1", "log1p", "exp2", "log2", "asinh", "acosh",
2116 "atanh", "hypot", "fmod", "sqrt", "fabs", "floor", "ceil", "abs", "div", "mod"}) and
2117 List.all(listAppend(ins, outs), isScalarCType);
2118 end match;
2119 then ();
2120 else ();
2121 end match;
2122 end externalServedByOmc;
2123
2124 protected function isScalarCType
2125 input String cty;
2126 output Boolean b = cty == "int" or cty == "double";
2127 end isScalarCType;
2128
2129 protected function variableCType
2130 "A scalar variable's C type; fails for an array or anything else."
2131 input SimCodeFunction.Variable v;
2132 output String cty;
2133 protected
2134 DAE.Type ty;
2135 algorithm
2136
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
8 SimCodeFunction.VARIABLE(ty = ty, instDims = {}) := v;
2137
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 (cty, false) := externalScalarType(ty);
2138 end variableCType;
2139
2140 protected function externalArgIsInput
2141 input SimCodeFunction.SimExtArg arg;
2142 output Boolean b;
2143 algorithm
2144 b := match arg
2145 3 case SimCodeFunction.SIMEXTARG() then arg.isInput;
2146 case SimCodeFunction.SIMEXTARGEXP() then true;
2147 else false;
2148 end match;
2149 end externalArgIsInput;
2150
2151 protected function externalCSignature
2152 "The C parameter and return types of an external call, as the wasm-jit target
2153 declares them: an array, a record or an output passes by pointer, and FORTRAN
2154 77 passes everything by reference. Fails for a call it cannot make."
2155 input SimCodeFunction.Function f;
2156 output list<String> params = {};
2157 output String ret = "void";
2158 protected
2159 Boolean fortran, isArray;
2160 String cty, language;
2161 Integer outputIndex;
2162 list<Integer> written = {};
2163 list<SimCodeFunction.Variable> funArgs, outVars, biVars;
2164 list<SimCodeFunction.SimExtArg> extArgs;
2165 SimCodeFunction.SimExtArg extReturn;
2166 DAE.Type ty;
2167 algorithm
2168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 SimCodeFunction.EXTERNAL_FUNCTION(funArgs = funArgs, outVars = outVars, biVars = biVars, extArgs = extArgs,
2169 extReturn = extReturn, language = language) := f;
2170
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 true := listMember(language, {"C", "BUILTIN", "FORTRAN 77"});
2171
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
6 true := List.all(funArgs, variablePasses) and List.all(outVars, variablePasses) and
2172 List.all(biVars, variablePasses);
2173
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 fortran := language == "FORTRAN 77";
2174
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 6 times.
10 for arg in extArgs loop
2175 (cty, isArray, outputIndex) := match arg
2176 case SimCodeFunction.SIMEXTARGSIZE(outputIndex = outputIndex) then ("int", false, outputIndex);
2177 case SimCodeFunction.SIMEXTARG(type_ = ty, outputIndex = outputIndex)
2178 algorithm
2179 4 (cty, isArray) := externalScalarType(ty);
2180 4 then (cty, isArray, outputIndex);
2181 case SimCodeFunction.SIMEXTARGEXP(type_ = ty)
2182 algorithm
2183 ✗ (cty, isArray) := externalScalarType(ty);
2184 ✗ then (cty, isArray, 0);
2185 end match;
2186 // Each output is written by one argument at most.
2187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if outputIndex > 0 then
2188 ✗ false := listMember(outputIndex, written);
2189 written := outputIndex :: written;
2190 end if;
2191
8/12
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 2 times.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
6 params := (if cty == "record" then "void" else cty) +
2192 (if outputIndex > 0 or fortran or isArray or cty == "record" then "*" else "") :: params;
2193 end for;
2194 6 params := listReverse(params);
2195 ret := match extReturn
2196 case SimCodeFunction.SIMNOEXTARG() then "void";
2197 case SimCodeFunction.SIMEXTARG(type_ = ty)
2198 algorithm
2199
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 (cty, false) := externalScalarType(ty);
2200 then cty;
2201 end match;
2202 end externalCSignature;
2203
2204 protected function externalUnsupported
2205 "Why the wasm-jit target cannot call an external function."
2206 input SimCodeFunction.Function f;
2207 output String why;
2208 protected
2209 String language;
2210 list<SimCodeFunction.Variable> funArgs, outVars, biVars;
2211 algorithm
2212 ✗ SimCodeFunction.EXTERNAL_FUNCTION(funArgs = funArgs, outVars = outVars, biVars = biVars, language = language) := f;
2213 ✗ if not listMember(language, {"C", "BUILTIN", "FORTRAN 77"}) then
2214 ✗ why := "external language \"" + language + "\" is not supported";
2215 elseif not (List.all(funArgs, variablePasses) and List.all(outVars, variablePasses) and
2216 List.all(biVars, variablePasses)) then
2217 why := "a variable of the function has a type that cannot be marshalled";
2218 else
2219 why := "an argument or the result of the call cannot be marshalled";
2220 end if;
2221 end externalUnsupported;
2222
2223 protected function elaborateFunctionCode
2224 "The SimCode of an instantiated function, as translateFunctions builds it."
2225 input output FCore.Cache cache;
2226 input FCore.Graph env;
2227 input Absyn.Program program;
2228 input Absyn.Path path;
2229 output SimCodeFunction.FunctionCode fnCode;
2230 protected
2231 DAE.Function daeMainFunction;
2232 list<DAE.Function> dependencies, daeElements;
2233 list<DAE.Type> metarecordTypes;
2234 list<DAE.Exp> literals;
2235 SimCodeFunction.Function mainFunction;
2236 list<SimCodeFunction.Function> fns;
2237 list<SimCodeFunction.RecordDeclaration> extraRecordDecls;
2238 list<String> includes, includeDirs, libs, libPaths;
2239 algorithm
2240 6 (cache, daeMainFunction, dependencies, metarecordTypes) := collectDependencies(cache, env, path);
2241 6 (daeElements, literals) := SimCodeFunctionUtil.findLiterals(daeMainFunction::dependencies);
2242
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 (mainFunction::fns, extraRecordDecls, includes, includeDirs, libs, libPaths) := SimCodeFunctionUtil.elaborateFunctions(program, daeElements, metarecordTypes, literals, {});
2243 6 fnCode := SimCodeFunction.FUNCTIONCODE(generateFunctionFileName(path), SOME(mainFunction), fns, literals, includes,
2244 SimCodeFunctionUtil.createMakefileParams(includeDirs, libs, libPaths, true), extraRecordDecls);
2245 end elaborateFunctionCode;
2246
2247 protected function externalCFunctionPaths
2248 "The external \"C\" functions and the external object classes in a class."
2249 input Absyn.Path path;
2250 input Absyn.Class cls;
2251 input output list<Absyn.Path> paths;
2252 protected
2253 Option<String> lang;
2254 list<Absyn.ElementItem> elts;
2255 algorithm
2256
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 3 times.
7 if AbsynUtil.isFunctionRestriction(cls.restriction) then
2257
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if not cls.partialPrefix then
2258 try
2259
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 Absyn.EXTERNAL(externalDecl = Absyn.EXTERNALDECL(lang = lang)) := AbsynUtil.getExternalDecl(cls);
2260
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
4 if Util.getOptionOrDefault(lang, "C") == "C" then
2261 paths := path :: paths;
2262 end if;
2263 else
2264 end try;
2265 end if;
2266 4 return;
2267 end if;
2268 3 elts := AbsynUtil.getElementItemsInClass(cls);
2269
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
3 if List.any(elts, isExternalObjectExtends) then
2270 paths := path :: paths;
2271 1 return;
2272 end if;
2273
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
13 for e in elts loop
2274 paths := match e
2275 local
2276 Absyn.Class c;
2277 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.CLASSDEF(class_ = c)))
2278 6 then externalCFunctionPaths(AbsynUtil.suffixPath(path, c.name), c, paths);
2279 5 else paths;
2280 end match;
2281 end for;
2282 end externalCFunctionPaths;
2283
2284 protected function isExternalObjectExtends
2285 input Absyn.ElementItem e;
2286 output Boolean b;
2287 algorithm
2288 b := match e
2289 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.EXTENDS(path = Absyn.IDENT("ExternalObject")))) then true;
2290 else false;
2291 end match;
2292 end isExternalObjectExtends;
2293
2294 protected function matchQualifiedCalls
2295 "Collects the packages used by the functions"
2296 input DAE.Exp inExp;
2297 input list<String> inAcc;
2298 output DAE.Exp outExp = inExp;
2299 output list<String> outAcc;
2300 algorithm
2301 outAcc := match inExp
2302 local
2303 String name;
2304
2305 case DAE.REDUCTION(reductionInfo = DAE.REDUCTIONINFO(path = Absyn.FULLYQUALIFIED(Absyn.QUALIFIED(name = name))))
2306 ✗ then List.consOnTrue(not listMember(name, inAcc), name, inAcc);
2307
2308 case DAE.CALL(path = Absyn.FULLYQUALIFIED(Absyn.QUALIFIED(name = name)),
2309 attr = DAE.CALL_ATTR(builtin = false))
2310 ✗ then List.consOnTrue(not listMember(name, inAcc), name, inAcc);
2311
2312 case DAE.CREF(componentRef = DAE.CREF_QUAL(ident = name),
2313 ty = DAE.T_FUNCTION_REFERENCE_FUNC(builtin = false))
2314 ✗ then List.consOnTrue(not listMember(name, inAcc), name, inAcc);
2315
2316 case DAE.PARTEVALFUNCTION(path = Absyn.FULLYQUALIFIED(Absyn.QUALIFIED(name = name)))
2317 ✗ then List.consOnTrue(not listMember(name, inAcc), name, inAcc);
2318
2319 else inAcc;
2320 end match;
2321 end matchQualifiedCalls;
2322
2323 protected function instantiateDaeFunctions
2324 input FCore.Cache icache;
2325 input FCore.Graph ienv;
2326 input list<Absyn.Path> ipaths;
2327 output FCore.Cache outCache;
2328 algorithm
2329 outCache := match (icache,ienv,ipaths)
2330 local
2331 Absyn.Path path;
2332 FCore.Cache cache; FCore.Graph env;
2333 list<Absyn.Path> paths;
2334 case (cache,_,{}) then cache;
2335 case (cache,env,path::paths)
2336 algorithm
2337 // print("force inst: " + AbsynUtil.pathString(path));
2338 ✗ (cache,Util.SUCCESS()) := Static.instantiateDaeFunctionForceInst(cache,env,path,false,NONE(),true);
2339 // print(" ok\n");
2340 ✗ cache := instantiateDaeFunctions(cache,env,paths);
2341 then cache;
2342 end match;
2343 end instantiateDaeFunctions;
2344
2345 function generateFunctions
2346 input FCore.Cache icache;
2347 input FCore.Graph ienv;
2348 input Absyn.Program p;
2349 input SCode.Program fullScodeProgram;
2350 input list<SCode.Element> isp;
2351 input Boolean cleanCache;
2352 output FCore.Cache cache;
2353 output FCore.Graph env;
2354 algorithm
2355 (cache,env) := match (icache, ienv, isp)
2356 local
2357 String name;
2358 list<SCode.Element> sp;
2359 String file;
2360 Integer n;
2361 SourceInfo info;
2362 SCode.Element cl;
2363 SCode.Restriction restr;
2364
2365 case (cache, env, {}) then (cache,env);
2366 case (cache, env, (cl as SCode.CLASS(name=name,encapsulatedPrefix=SCode.ENCAPSULATED(),restriction=restr,info=info))::sp)
2367 algorithm
2368 () := match restr
2369 case SCode.R_PACKAGE() then ();
2370 case SCode.R_UNIONTYPE() then ();
2371 else
2372 algorithm
2373 ✗ Error.addSourceMessage(Error.INTERNAL_ERROR, {"Only package and uniontype is supported as top-level classes in OpenModelica."}, info);
2374 ✗ then fail();
2375 end match;
2376 ✗ (cache,env) := generateFunctions2(cache,env,p,fullScodeProgram,cl,name,info,cleanCache);
2377 ✗ (cache,env) := generateFunctions(cache,env,p,fullScodeProgram,sp,cleanCache);
2378 then (cache,env);
2379 case (_, _, SCode.CLASS(encapsulatedPrefix=SCode.NOT_ENCAPSULATED(),name=name,info=info as SOURCEINFO(fileName=file))::_)
2380 algorithm
2381 ✗ (n,_) := System.regex(file, "ModelicaBuiltin.mo$", 1, false, false);
2382 ✗ Error.assertion(n > 0, "Not an encapsulated class (required for separate compilation): " + name, info);
2383 ✗ then fail();
2384 end match;
2385 end generateFunctions;
2386
2387 function generateFunctions2
2388 input FCore.Cache icache;
2389 input FCore.Graph ienv;
2390 input Absyn.Program p;
2391 input SCode.Program sp;
2392 input SCode.Element cl;
2393 input String name;
2394 input SourceInfo info;
2395 input Boolean cleanCache;
2396 output FCore.Cache cache;
2397 output FCore.Graph env;
2398 algorithm
2399 (cache,env) := matchcontinue (icache, ienv, info)
2400 local
2401 list<String> dependencies,strs;
2402 list<Absyn.Path> paths, pathsMetarecord;
2403 AvlTreePathFunction.Tree funcs;
2404 list<DAE.Function> d;
2405 String file,nameHeader,str;
2406 Absyn.Path path;
2407 list<SCode.Element> elements;
2408 list<DAE.Type> metarecords;
2409 DAE.Type t;
2410
2411 case (cache, env, SOURCEINFO(fileName=file))
2412 algorithm
2413 ✗ (1,_) := System.regex(file, "ModelicaBuiltin.mo$", 1, false, false);
2414 then (cache,env);
2415
2416 case (cache, env, _)
2417 algorithm
2418 ✗ cache := if cleanCache then FCore.emptyCache() else cache;
2419
2420 ✗ if SCodeUtil.isPartial(cl) then
2421 paths := {};
2422 ✗ pathsMetarecord := {};
2423 else
2424 ✗ path := Absyn.FULLYQUALIFIED(Absyn.IDENT(name));
2425 ✗ elements := getNonPartialElementsForInstantiatedClass(sp, cl, path);
2426 ✗ (paths, pathsMetarecord) := List.fold22(elements, findFunctionsToCompile, path, sp, {}, {});
2427 end if;
2428
2429 metarecords := {};
2430 ✗ for mr in pathsMetarecord loop
2431 ✗ (cache,t) := Lookup.lookupType(cache, env, mr, SOME(info));
2432 ✗ metarecords := t::metarecords;
2433 end for;
2434
2435 ✗ cache := instantiateDaeFunctions(cache, env, paths);
2436 // The inst cache is normally released by Inst.instantiateClass, but
2437 // since findFunctionToCompile might need to call it many times we want
2438 // to keep the cache for performance and release it here instead.
2439 ✗ InstHashTable.release();
2440 ✗ funcs := FCore.getFunctionTree(cache);
2441 ✗ d := List.map2(paths, DAEUtil.getNamedFunctionWithError, funcs, info);
2442 ✗ (_,(_,dependencies)) := DAEUtil.traverseDAEFunctions(d,Expression.traverseSubexpressionsHelper,(matchQualifiedCalls,{}));
2443 // print(name + " has dependencies: " + stringDelimitList(dependencies,",") + "\n");
2444 ✗ dependencies := List.sort(dependencies,Util.strcmpBool);
2445 ✗ dependencies := List.map1(dependencies,stringAppend,".h");
2446 ✗ nameHeader := name + ".h";
2447 ✗ strs := List.map1r(nameHeader::dependencies, stringAppend, "$(GEN_DIR)");
2448 ✗ System.writeFile(name + ".deps", "$(GEN_DIR)" + name + ".o: $(GEN_DIR)" + name + ".c" + " " + stringDelimitList(strs," "));
2449 ✗ dependencies := List.map1(dependencies,stringAppend,"\"");
2450 ✗ dependencies := List.map1r(dependencies,stringAppend,"#include \"");
2451 ✗ translateFunctions(p, name, NONE(), d, {}, dependencies);
2452 ✗ str := Tpl.tplString(Unparsing.programExternalHeaderFromTypes, metarecords);
2453 ✗ System.writeFile(name + "_records.c","#include <meta/meta_modelica.h>\n" + str);
2454 ✗ cache := if cleanCache then icache else cache;
2455 then (cache,env);
2456 else
2457 algorithm
2458 ✗ Error.addSourceMessage(Error.SEPARATE_COMPILATION_PACKAGE_FAILED,{name},info);
2459 ✗ then fail();
2460 end matchcontinue;
2461 end generateFunctions2;
2462
2463 function findFunctionsToCompile
2464 input SCode.Element elt;
2465 input Absyn.Path pathPrefix;
2466 input SCode.Program sp;
2467 input list<Absyn.Path> acc;
2468 input list<Absyn.Path> accMetarecord;
2469 output list<Absyn.Path> paths;
2470 output list<Absyn.Path> pathsMetarecord;
2471 protected
2472 String name;
2473 Absyn.Path path;
2474 list<SCode.Element> elements;
2475 algorithm
2476 ✗ SCode.CLASS(name=name) := elt;
2477 ✗ path := AbsynUtil.joinPaths(pathPrefix, Absyn.IDENT(name));
2478 ✗ paths := if SCodeUtil.isFunction(elt) then path::acc else acc;
2479 pathsMetarecord := match elt
2480 case SCode.CLASS(restriction=SCode.R_METARECORD()) then path::accMetarecord;
2481 else accMetarecord;
2482 end match;
2483 ✗ elements := getNonPartialElementsForInstantiatedClass(sp, elt, path);
2484 ✗ (paths,pathsMetarecord) := List.fold22(elements, findFunctionsToCompile, path, sp, paths, pathsMetarecord);
2485 end findFunctionsToCompile;
2486
2487 function getNonPartialElementsForInstantiatedClass "Gets the non-partial elements returned by instantiating the given path"
2488 input SCode.Program sp;
2489 input SCode.Element cl;
2490 input Absyn.Path p;
2491 output list<SCode.Element> elts;
2492 protected
2493 FCore.Graph env;
2494 Boolean skip;
2495 list<SCode.Element> eltsTmp;
2496 algorithm
2497 skip := match cl
2498 case SCode.CLASS(classDef=SCode.CLASS_EXTENDS()) then false;
2499 ✗ case SCode.CLASS(classDef=SCode.PARTS(elementLst=eltsTmp)) then not List.any(eltsTmp, SCodeUtil.isElementExtendsOrClassExtends);
2500 else true;
2501 end match;
2502 ✗ if not skip then
2503 try
2504 ✗ ErrorExt.setCheckpoint("getNonPartialElementsForInstantiatedClass");
2505 ✗ (, env) := Inst.instantiateClass(FCore.emptyCache(), InnerOuter.emptyInstHierarchy, sp, AbsynUtil.makeNotFullyQualified(p), doSCodeDep=false, clearCache = false);
2506 ✗ elts := FCore.RefTree.fold(FNode.children(FNode.fromRef(FGraph.lastScopeRef(env))),
2507 addNonPartialClassRef, {});
2508 ✗ ErrorExt.rollBack("getNonPartialElementsForInstantiatedClass");
2509 ✗ return;
2510 else
2511 end try;
2512 ✗ ErrorExt.rollBack("getNonPartialElementsForInstantiatedClass");
2513 end if;
2514 // Failed to instantiate the class; perhaps due to being a function
2515 // that cannot be instantiated using model restrictions.
2516 elts := match cl
2517 ✗ case SCode.CLASS(classDef=SCode.PARTS(elementLst=elts)) then list(e for e guard (not SCodeUtil.isPartial(e)) and SCodeUtil.isClass(e) in elts);
2518 else {};
2519 end match;
2520 end getNonPartialElementsForInstantiatedClass;
2521
2522 protected function addNonPartialClassRef
2523 input FCore.Name name;
2524 input FCore.Ref ref;
2525 input list<SCode.Element> accum;
2526 output list<SCode.Element> classes;
2527 protected
2528 SCode.Element e;
2529 algorithm
2530 classes := match FNode.fromRef(ref)
2531 case FCore.N(data = FCore.CL(e = e as SCode.CLASS(partialPrefix = SCode.NOT_PARTIAL())))
2532 then e :: accum;
2533
2534 else accum;
2535 end match;
2536 end addNonPartialClassRef;
2537
2538 public function cevalCallFunction "This function evaluates CALL expressions, i.e. function calls.
2539 They are currently evaluated by generating code for the function and
2540 then dynamicly load the function and call it."
2541 input FCore.Cache inCache;
2542 input FCore.Graph inEnv;
2543 input DAE.Exp inExp;
2544 input list<Values.Value> inValuesValueLst;
2545 input Boolean impl;
2546 input Absyn.Msg inMsg;
2547 input Integer numIter;
2548 output FCore.Cache outCache;
2549 output Values.Value outValue;
2550 algorithm
2551 (outCache,outValue) := matchcontinue (inCache, inEnv, inExp, inValuesValueLst, inMsg)
2552 local
2553 Values.Value newval;
2554 FCore.Graph env;
2555 Absyn.Path funcpath;
2556 list<DAE.Exp> expl;
2557 list<Values.Value> vallst, pubVallst, proVallst;
2558 Absyn.Msg msg;
2559 FCore.Cache cache;
2560 Absyn.Path complexName;
2561 list<DAE.Var> pubVarLst, proVarLst, varLst;
2562 list<String> pubVarNames, proVarNames, varNames;
2563 DAE.Type ty;
2564 Boolean bIsCompleteFunction;
2565
2566 // External functions that are "known" should be evaluated without compilation, e.g. all math functions
2567 case (cache, env, (DAE.CALL(path = funcpath)), vallst, msg)
2568 algorithm
2569 77790 (cache,newval) := Ceval.cevalKnownExternalFuncs(cache,env, funcpath, vallst, msg);
2570 then
2571 (cache,newval);
2572
2573 // This case prevents the constructor call of external objects of being evaluated
2574 case (cache, env, (DAE.CALL(path = funcpath)), _, msg)
2575 algorithm
2576
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 75525 times.
75525 true := FGraph.isNotEmpty(env);
2577 75525 cevalIsExternalObjectConstructor(cache,funcpath,env,msg);
2578 1 then
2579 fail();
2580
2581 // Record constructors
2582 case(cache, env, (DAE.CALL(path = funcpath,attr = DAE.CALL_ATTR(ty = DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(complexName), varLst=varLst)))), pubVallst, msg)
2583 algorithm
2584
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6279 times.
6279 if Flags.isSet(Flags.DYN_LOAD) then
2585 ✗ Debug.traceln("CALL: record constructor: func: " + AbsynUtil.pathString(funcpath) + " type path: " + AbsynUtil.pathString(complexName));
2586 end if;
2587
2/2
✓ Branch 1 taken 5585 times.
✓ Branch 2 taken 694 times.
6279 true := AbsynUtil.pathEqual(funcpath,complexName);
2588 694 (pubVarLst,proVarLst) := List.splitOnTrue(varLst,Types.isPublicVar);
2589 694 expl := List.map1(proVarLst, Types.getBindingExp, funcpath);
2590 694 (cache,proVallst) := Ceval.cevalList(cache, env, expl, impl, msg, numIter);
2591 694 pubVarNames := List.map(pubVarLst,Expression.varName);
2592 694 proVarNames := List.map(proVarLst,Expression.varName);
2593 694 varNames := listAppend(pubVarNames, proVarNames);
2594 694 vallst := listAppend(pubVallst, proVallst);
2595 // fprintln(Flags.DYN_LOAD, "CALL: record constructor: [success] func: " + AbsynUtil.pathString(funcpath));
2596 694 then
2597 (cache,Values.RECORD(funcpath,vallst,varNames,-1));
2598
2599 // evaluate or generate non-partial and non-replaceable functions
2600 case (cache, env, DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR(ty = ty, builtin = false)), _, msg)
2601 algorithm
2602
2/2
✓ Branch 0 taken 38326 times.
✓ Branch 1 taken 38325 times.
76651 failure(cevalIsExternalObjectConstructor(cache, funcpath, env, msg));
2603
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 38325 times.
38325 if Flags.isSet(Flags.DYN_LOAD) then
2604 ✗ Debug.traceln("CALL: try to evaluate or generate function: " + AbsynUtil.pathString(funcpath));
2605 end if;
2606
2607 38325 bIsCompleteFunction := isCompleteFunction(cache, env, funcpath);
2608
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 38325 times.
38325 false := Types.hasMetaArray(ty);
2609
2610
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 38325 times.
38325 if Flags.isSet(Flags.DYN_LOAD) then
2611 ✗ Debug.traceln("CALL: is complete function: " + AbsynUtil.pathString(funcpath) + " " + (if bIsCompleteFunction then "[true]" else "[false]"));
2612 end if;
2613 38325 (cache, newval) := cevalCallFunctionEvaluateOrGenerate(inCache,inEnv,inExp,inValuesValueLst,impl,inMsg,bIsCompleteFunction);
2614
2615 // Debug.fprintln(Flags.DYN_LOAD, "CALL: constant evaluation success: " + AbsynUtil.pathString(funcpath));
2616 then
2617 (cache, newval);
2618
2619 // partial and replaceable functions should not be evaluated!
2620 case (cache, env, DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR( builtin = false)), _, msg)
2621 algorithm
2622
2/2
✓ Branch 0 taken 235 times.
✓ Branch 1 taken 234 times.
469 failure(cevalIsExternalObjectConstructor(cache, funcpath, env, msg));
2623
2/2
✓ Branch 1 taken 114 times.
✓ Branch 2 taken 120 times.
234 false := isCompleteFunction(cache, env, funcpath);
2624
2625
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
120 if Flags.isSet(Flags.DYN_LOAD) then
2626 ✗ Debug.traceln("CALL: constant evaluation failed (not complete function): " + AbsynUtil.pathString(funcpath));
2627 end if;
2628 120 then
2629 fail();
2630 /*
2631 case (cache,env, DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR(ty = ty, builtin = false)), _, _, msg as Absyn.MSG(info), _)
2632 algorithm
2633 failure(cevalIsExternalObjectConstructor(cache, funcpath, env, msg));
2634 true = isCompleteFunction(cache, env, funcpath);
2635 true = Types.hasMetaArray(ty);
2636 str = ExpressionBasics.printExpStr(inExp);
2637 Error.addSourceMessage(Error.FUNCTION_RETURNS_META_ARRAY, {str}, info);
2638 then fail();
2639 */
2640 else fail();
2641
2642 end matchcontinue;
2643 end cevalCallFunction;
2644
2645 protected
2646
2647 function cevalCallFunctionEvaluateOrGenerate
2648 "This function evaluates CALL expressions, i.e. function calls.
2649 They are currently evaluated by generating code for the function and
2650 then dynamicly load the function and call it."
2651 input FCore.Cache inCache;
2652 input FCore.Graph inEnv;
2653 input DAE.Exp inExp;
2654 input list<Values.Value> inValuesValueLst;
2655 input Boolean impl;
2656 input Absyn.Msg inMsg;
2657 input Boolean bIsCompleteFunction;
2658 output FCore.Cache outCache;
2659 output Values.Value outValue;
2660 protected
2661 Integer numCheckpoints;
2662 algorithm
2663 // Only add a stack overflow checkpoint for the top-most cevalCallFunctionEvaluateOrGenerate
2664
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 38325 times.
✓ Branch 5 taken 6921 times.
✓ Branch 6 taken 31404 times.
38325 if isNone(getGlobalRoot(Global.stackoverFlowIndex)) then
2665 6921 setGlobalRoot(Global.stackoverFlowIndex, SOME(1));
2666 6921 numCheckpoints:=ErrorExt.getNumCheckpoints();
2667 try
2668 6921 StackOverflow.clearStacktraceMessages();
2669 6921 (outCache,outValue) := cevalCallFunctionEvaluateOrGenerate2(inCache,inEnv,inExp,inValuesValueLst,impl,inMsg,bIsCompleteFunction);
2670 else
2671 ✗ setGlobalRoot(Global.stackoverFlowIndex, NONE());
2672 ✗ ErrorExt.rollbackNumCheckpoints(ErrorExt.getNumCheckpoints()-numCheckpoints);
2673 ✗ Error.addInternalError(StackOverflow.errorPrefix() + " when evaluating function call: "+ExpressionBasics.printExpStr(inExp)+"...\n"+stringDelimitList(StackOverflow.readableStacktraceMessages(), "\n"), match inMsg local SourceInfo info; case Absyn.MSG(info) then info; else sourceInfo(); end match);
2674 /* Do not fail or we can loop too much */
2675 ✗ StackOverflow.clearStacktraceMessages();
2676 outCache := inCache;
2677 ✗ outValue := Values.META_FAIL();
2678 end try annotation(__OpenModelica_stackOverflowCheckpoint=true);
2679 6889 setGlobalRoot(Global.stackoverFlowIndex, NONE());
2680 else
2681 31404 (outCache,outValue) := cevalCallFunctionEvaluateOrGenerate2(inCache,inEnv,inExp,inValuesValueLst,impl,inMsg,bIsCompleteFunction);
2682 end if;
2683 end cevalCallFunctionEvaluateOrGenerate;
2684
2685 function cevalCallFunctionEvaluateOrGenerate2
2686 "This function evaluates CALL expressions, i.e. function calls.
2687 They are currently evaluated by generating code for the function and
2688 then dynamicly load the function and call it."
2689 input FCore.Cache inCache;
2690 input FCore.Graph inEnv;
2691 input DAE.Exp inExp;
2692 input list<Values.Value> inValuesValueLst;
2693 input Boolean impl;
2694 input Absyn.Msg inMsg;
2695 input Boolean bIsCompleteFunction;
2696 output FCore.Cache outCache;
2697 output Values.Value outValue;
2698 algorithm
2699 (outCache,outValue) := matchcontinue (inCache, inEnv, inExp, inValuesValueLst, inMsg)
2700 local
2701 Values.Value newval;
2702 FCore.Graph env;
2703 Absyn.Path funcpath;
2704 Boolean print_debug;
2705 list<Values.Value> vallst;
2706 Absyn.Msg msg;
2707 FCore.Cache cache;
2708 Absyn.Program p;
2709 Integer libHandle, funcHandle;
2710 String funcstr,fileName;
2711 SourceInfo info;
2712 Absyn.Within w;
2713 SCode.Element sc;
2714 DAE.Function func;
2715
2716 // try function interpretation
2717 case (cache, env, DAE.CALL(path = funcpath, attr = DAE.CALL_ATTR(builtin = false)), vallst, msg)
2718 algorithm
2719
2/2
✓ Branch 1 taken 84 times.
✓ Branch 2 taken 38241 times.
38325 true := Flags.isSet(Flags.EVAL_FUNC);
2720
2/2
✓ Branch 0 taken 38241 times.
✓ Branch 1 taken 38241 times.
76482 failure(cevalIsExternalObjectConstructor(cache, funcpath, env, msg));
2721 // bcall1(Flags.isSet(Flags.DYN_LOAD), print,"[dynload]: try constant evaluation: " + AbsynUtil.pathString(funcpath) + "\n");
2722
2723 try
2724 38241 func := FCore.getCachedInstFunc(cache, funcpath);
2725 else
2726
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 63 times.
65 (cache,
2727 sc as SCode.CLASS(partialPrefix = SCode.NOT_PARTIAL()),
2728 env) := Lookup.lookupClass(cache, env, funcpath);
2729 63 isCevaluableFunction(sc);
2730 37 (cache, env, _) := InstFunction.implicitFunctionInstantiation(
2731 cache,
2732 env,
2733 InnerOuter.emptyInstHierarchy,
2734 DAE.NOMOD(),
2735 DAE.NOPRE(),
2736 sc,
2737 {});
2738 1 func := FCore.getCachedInstFunc(cache, funcpath);
2739 end try;
2740
2741 38177 (cache, newval) := CevalFunction.evaluate(cache, env, func, vallst);
2742 // bcall1(Flags.isSet(Flags.DYN_LOAD), print, "[dynload]: constant evaluation SUCCESS: " + AbsynUtil.pathString(funcpath) + "\n");
2743 then
2744 (cache, newval);
2745
2746 // not in CF list, we have a symbol table, generate function and update symtab
2747 case (cache, env, (DAE.CALL(path = funcpath,attr = DAE.CALL_ATTR( builtin = false))), vallst, msg)
2748 guard (bIsCompleteFunction and Flags.isSet(Flags.GEN)) // yeha! we have a symboltable!
2749 algorithm
2750
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 162 times.
324 failure(cevalIsExternalObjectConstructor(cache,funcpath,env,msg));
2751
2752
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 162 times.
162 if Flags.isSet(Flags.DYN_LOAD) then
2753 ✗ print("[dynload]: [SOME SYMTAB] not in in CF list: " + AbsynUtil.pathString(funcpath) + "\n");
2754 end if;
2755
2756 162 p := SymbolTable.getAbsyn();
2757 // now is safe to generate code
2758 162 (cache, funcstr, fileName) := cevalGenerateFunction(cache, env, p, funcpath);
2759 140 print_debug := Flags.isSet(Flags.DYN_LOAD);
2760 140 execStatReset();
2761
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 140 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
140 if Config.simCodeTarget() == "wasm-jit" then
2762 // JIT and run the generated WebAssembly module in-process; no shared
2763 // object to load or free.
2764 ✗ newval := CodegenWasmJitFunctions.loadAndExecute(fileName, funcstr, vallst);
2765 else
2766 140 libHandle := System.loadLibrary(fileName + Autoconf.dllExt, relativePath = true, printDebug = print_debug);
2767 140 funcHandle := System.lookupFunction(libHandle, stringAppend("in_", funcstr));
2768 140 newval := DynLoad.executeFunction(funcHandle, vallst, print_debug);
2769 // lookupFunction takes a reference on the library, so freeing the
2770 // library alone only drops the count from two to one and the shared
2771 // object is never unloaded. On Windows that keeps the file locked, and
2772 // the next call to the same function cannot relink its .dll: the code
2773 // generation fails and the call silently evaluates to nothing.
2774 //
2775 // Only Windows needs the unload. Unix can relink a loaded .so, since
2776 // that just replaces the inode, and unloading there would change
2777 // behaviour: a generated function's shared object carries static state
2778 // that currently survives between calls in a session, e.g. the seed
2779 // behind System.realRand (openmodelica/bootstrapping/System.mos).
2780 if Autoconf.os == "Windows_NT" then
2781 System.freeFunction(funcHandle, print_debug);
2782 end if;
2783 140 System.freeLibrary(libHandle, print_debug);
2784 end if;
2785 140 execStat("executeFunction("+AbsynUtil.pathString(funcpath)+")");
2786 // update the build time in the class!
2787
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 140 times.
140 Absyn.CLASS(restriction=Absyn.R_FUNCTION(_),info=info) := ProgramUtil.getPathedClassInProgram(funcpath, p);
2788
2789 140 w := ProgramUtil.buildWithin(funcpath);
2790
2791
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 140 times.
140 if Flags.isSet(Flags.DYN_LOAD) then
2792 ✗ print("[dynload]: Updating build time for function path: " + AbsynUtil.pathString(funcpath) + " within: " + Dump.unparseWithin(w) + "\n");
2793 end if;
2794
2795 // p = Interactive.updateProgram(Absyn.PROGRAM({Absyn.CLASS(name,ppref,fpref,epref,Absyn.R_FUNCTION(funcRest),body,info)},w,ts), p);
2796
2797
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 140 times.
140 if Flags.isSet(Flags.DYN_LOAD) then
2798 ✗ print("[dynload]: [SOME SYMTAB] not in in CF list [finished]: " +
2799 AbsynUtil.pathString(funcpath) + "\n");
2800 end if;
2801 140 then
2802 (cache,newval);
2803
2804 case (_, _, (DAE.CALL(path = funcpath)), _, _)
2805 algorithm
2806
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 234 times.
234 if Flags.isSet(Flags.DYN_LOAD) then
2807 ✗ print("[dynload]: FAILED to constant evaluate function: " + AbsynUtil.pathString(funcpath) + "\n");
2808 end if;
2809 //TODO: readd this when testsuite is okay.
2810 //Error.addMessage(Error.FAILED_TO_EVALUATE_FUNCTION, {error_Str});
2811
2/2
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 212 times.
234 false := Flags.isSet(Flags.GEN);
2812
1/2
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
212 true := Flags.isSet(Flags.FAILTRACE);
2813 ✗ Debug.trace("- codegeneration is turned off. switch \"nogen\" flag off\n");
2814 ✗ then
2815 fail();
2816
2817 end matchcontinue;
2818 end cevalCallFunctionEvaluateOrGenerate2;
2819
2820 function cevalIsExternalObjectConstructor
2821 input FCore.Cache cache;
2822 input Absyn.Path funcpath;
2823 input FCore.Graph env;
2824 input Absyn.Msg msg;
2825 protected
2826 Absyn.Path funcpath2;
2827 DAE.Type tp;
2828 Option<SourceInfo> info;
2829 algorithm
2830 () := match(env, msg)
2831 ✗ case (FCore.EG(_), Absyn.NO_MSG()) then fail();
2832 case (_, Absyn.NO_MSG())
2833 algorithm
2834
5/6
✗ Branch 1 not taken.
✓ Branch 2 taken 9118 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 9112 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 3 times.
9162 (funcpath2, Absyn.IDENT("constructor")) := AbsynUtil.splitQualAndIdentPath(funcpath);
2835
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 info := if valueEq(msg, Absyn.NO_MSG()) then NONE() else SOME(Absyn.dummyInfo);
2836 3 (_, tp, _) := Lookup.lookupType(cache, env, funcpath2, info);
2837 3 Types.externalObjectConstructorType(tp);
2838 then
2839 ();
2840 end match;
2841 end cevalIsExternalObjectConstructor;
2842
2843 protected function checkLibraryUsage
2844 input String inLibrary;
2845 input Absyn.Exp inExp;
2846 output Boolean isUsed;
2847 algorithm
2848 isUsed := match inExp
2849 local
2850 String s;
2851 list<Absyn.Exp> exps;
2852
2853 ✗ case Absyn.STRING(s) then stringEq(s, inLibrary);
2854 case Absyn.ARRAY(exps)
2855 ✗ then List.isMemberOnTrue(inLibrary, exps, checkLibraryUsage);
2856 end match;
2857 end checkLibraryUsage;
2858
2859 function isCevaluableFunction
2860 "Checks if an element is a function or external function that can be evaluated
2861 by CevalFunction."
2862 input SCode.Element inElement;
2863 algorithm
2864 () := match inElement
2865 local
2866 String fid;
2867 SCode.Mod mod;
2868 Absyn.Exp lib;
2869
2870 //only some external functions.
2871 case SCode.CLASS(restriction = SCode.R_FUNCTION(SCode.FR_EXTERNAL_FUNCTION(_)),
2872 classDef = SCode.PARTS(externalDecl = SOME(SCode.EXTERNALDECL(
2873 funcName = SOME(fid),
2874 annotation_ = SOME(SCode.ANNOTATION(mod))))))
2875 algorithm
2876 ✗ SCode.MOD(binding = SOME(lib)) := Mod.getUnelabedSubMod(mod, "Library");
2877 ✗ true := checkLibraryUsage("Lapack", lib) or checkLibraryUsage("lapack", lib);
2878 ✗ isCevaluableFunction2(fid);
2879 then
2880 ();
2881
2882 // All other functions can be evaluated.
2883 case SCode.CLASS(restriction = SCode.R_FUNCTION(_)) then ();
2884
2885 end match;
2886 end isCevaluableFunction;
2887
2888 function isCevaluableFunction2
2889 "Checks if a function name belongs to a known external function that we can
2890 constant evaluate."
2891 input String inFuncName;
2892 algorithm
2893 () := match inFuncName
2894 local
2895 // Lapack functions.
2896 case "dgbsv" then ();
2897 case "dgeev" then ();
2898 case "dgegv" then ();
2899 case "dgels" then ();
2900 case "dgelsx" then ();
2901 case "dgelsy" then ();
2902 case "dgeqpf" then ();
2903 case "dgesv" then ();
2904 case "dgesvd" then ();
2905 case "dgetrf" then ();
2906 case "dgetri" then ();
2907 case "dgetrs" then ();
2908 case "dgglse" then ();
2909 case "dgtsv" then ();
2910 case "dorgqr" then ();
2911 end match;
2912 end isCevaluableFunction2;
2913
2914 function isSimpleAPIFunction
2915 input DAE.Type ty;
2916 output Boolean b;
2917 algorithm
2918 b := match ty
2919 ✗ case DAE.T_FUNCTION(functionAttributes=DAE.FUNCTION_ATTRIBUTES(isBuiltin=DAE.FUNCTION_BUILTIN())) then
2920 isSimpleAPIFunctionArg(ty.funcResultType) and
2921 ✗ min(match fa case DAE.FUNCARG() then isSimpleAPIFunctionArg(fa.ty); end match for fa in ty.funcArg);
2922 else false;
2923 end match;
2924 end isSimpleAPIFunction;
2925
2926 function isSimpleAPIFunctionArg
2927 input DAE.Type ty;
2928 output Boolean b;
2929 algorithm
2930 b := match ty
2931 case DAE.T_INTEGER() then true;
2932 case DAE.T_REAL() then true;
2933 case DAE.T_BOOL() then true;
2934 case DAE.T_STRING() then true;
2935 case DAE.T_NORETCALL() then true;
2936 ✗ case DAE.T_ARRAY() then isSimpleAPIFunctionArg(ty.ty);
2937 case DAE.T_CODE(ty=DAE.C_TYPENAME()) then true;
2938 ✗ case DAE.T_TUPLE() then min(isSimpleAPIFunctionArg(t) for t in ty.types);
2939 else false;
2940 end match;
2941 end isSimpleAPIFunctionArg;
2942
2943 function verifyInterfaceType
2944 input SCode.Element elt;
2945 input list<String> expected;
2946 algorithm
2947 () := matchcontinue (elt,expected)
2948 local
2949 String str,name;
2950 SCode.Annotation ann;
2951 SourceInfo info;
2952 case (SCode.CLASS(restriction=SCode.R_METARECORD(moved=true)),_) then ();
2953 case (SCode.CLASS(cmt=SCode.COMMENT(annotation_=SOME(ann))),name::_)
2954 algorithm
2955 ✗ SCode.MOD(binding = SOME(Absyn.STRING(str)), info = info) :=
2956 SCodeUtil.lookupAnnotation(ann, "__OpenModelica_Interface");
2957 ✗ Error.assertionOrAddSourceMessage(listMember(str, expected), Error.MISMATCHING_INTERFACE_TYPE, {str,name}, info);
2958 then ();
2959 else
2960 algorithm
2961 ✗ print(SCodeDump.unparseElementStr(elt)+"\n");
2962 ✗ Error.addSourceMessage(Error.MISSING_INTERFACE_TYPE,{},SCodeUtil.elementInfo(elt));
2963 ✗ then fail();
2964 end matchcontinue;
2965 end verifyInterfaceType;
2966
2967 function getInterfaceType
2968 input SCode.Element elt;
2969 input list<tuple<String,list<String>>> assoc;
2970 output list<String> it;
2971 algorithm
2972 it := matchcontinue elt
2973 local
2974 SCode.Annotation ann;
2975 String str;
2976 case SCode.CLASS(cmt=SCode.COMMENT(annotation_=SOME(ann)))
2977 algorithm
2978 ✗ SOME(Absyn.STRING(str)) := SCodeUtil.lookupAnnotationBinding(ann,"__OpenModelica_Interface");
2979 ✗ it := Util.assoc(str,assoc);
2980 then it;
2981 else
2982 algorithm
2983 ✗ Error.addSourceMessage(Error.MISSING_INTERFACE_TYPE,{},SCodeUtil.elementInfo(elt));
2984 ✗ then fail();
2985 end matchcontinue;
2986 end getInterfaceType;
2987
2988 function getInterfaceTypeAssocElt
2989 input Values.Value val;
2990 input SourceInfo info;
2991 output tuple<String,list<String>> assoc;
2992 algorithm
2993 assoc := match val
2994 local
2995 String str;
2996 list<String> strs;
2997 list<Values.Value> vals;
2998 case Values.ARRAY(valueLst=Values.STRING("")::_)
2999 algorithm
3000 ✗ Error.addSourceMessage(Error.MISSING_INTERFACE_TYPE,{},info);
3001 ✗ then fail();
3002 case Values.ARRAY(valueLst=Values.STRING(str)::vals)
3003 algorithm
3004 ✗ strs := List.select(List.map(vals,ValuesUtil.extractValueString), Util.isNotEmptyString);
3005 ✗ then ((str,str::strs));
3006 end match;
3007 end getInterfaceTypeAssocElt;
3008
3009 protected function buildDependencyGraph
3010 input String name;
3011 input SCode.Program sp;
3012 output list<String> edges;
3013 algorithm
3014 edges := match sp
3015 local
3016 list<SCode.Element> elts;
3017 case _
3018 algorithm
3019 ✗ SCode.CLASS(classDef=SCode.PARTS(elementLst=elts)) := List.getMemberOnTrue(name, sp, SCodeUtil.isClassNamed);
3020 ✗ elts := list(e for e guard SCodeUtil.isImport(e) in elts);
3021 ✗ then List.map(elts, importDependency);
3022 end match;
3023 end buildDependencyGraph;
3024
3025 protected function buildDependencyGraphPublicImports
3026 input String name;
3027 input SCode.Program sp;
3028 output list<String> edges;
3029 algorithm
3030 edges := match sp
3031 local
3032 list<SCode.Element> elts;
3033 case _
3034 algorithm
3035 ✗ SCode.CLASS(classDef=SCode.PARTS(elementLst=elts)) := List.getMemberOnTrue(name, sp, SCodeUtil.isClassNamed);
3036 ✗ elts := List.select(elts,SCodeUtil.elementIsPublicImport);
3037 ✗ then List.map(elts, importDependency);
3038 end match;
3039 end buildDependencyGraphPublicImports;
3040
3041 protected function buildTransitiveDependencyGraph
3042 input String name;
3043 input list<tuple<String,list<String>>> oldgraph;
3044 output list<String> edges;
3045 algorithm
3046 edges := matchcontinue oldgraph
3047 local
3048 String str;
3049 ✗ case _ then List.setDifference(Graph.allReachableNodes(({name},{}),oldgraph,stringEq),{name});
3050 else
3051 algorithm
3052 ✗ str := "CevalScript.buildTransitiveDependencyGraph failed: " + name;
3053 ✗ Error.addMessage(Error.INTERNAL_ERROR, {str});
3054 ✗ then fail();
3055 end matchcontinue;
3056 end buildTransitiveDependencyGraph;
3057
3058 protected function importDependency
3059 input SCode.Element simp;
3060 output String name;
3061 algorithm
3062 name := match simp
3063 local
3064 Absyn.Import imp;
3065 SourceInfo info;
3066 String str;
3067 Absyn.Path path;
3068 ✗ case SCode.IMPORT(imp=Absyn.NAMED_IMPORT(path=path)) then AbsynUtil.pathFirstIdent(path);
3069 ✗ case SCode.IMPORT(imp=Absyn.NAMED_IMPORT(path=path)) then AbsynUtil.pathFirstIdent(path);
3070 ✗ case SCode.IMPORT(imp=Absyn.QUAL_IMPORT(path=path)) then AbsynUtil.pathFirstIdent(path);
3071 ✗ case SCode.IMPORT(imp=Absyn.UNQUAL_IMPORT(path=path)) then AbsynUtil.pathFirstIdent(path);
3072 ✗ case SCode.IMPORT(imp=Absyn.GROUP_IMPORT(prefix=path)) then AbsynUtil.pathFirstIdent(path);
3073 case SCode.IMPORT(imp=imp,info=info)
3074 algorithm
3075 ✗ str := "CevalScript.importDependency could not handle:" + Dump.unparseImportStr(imp);
3076 ✗ Error.addSourceMessage(Error.INTERNAL_ERROR,{str},info);
3077 ✗ then fail();
3078 end match;
3079 end importDependency;
3080
3081 protected function compareNumberOfDependencies
3082 input tuple<String,list<String>> node1;
3083 input tuple<String,list<String>> node2;
3084 output Boolean cmp;
3085 protected
3086 list<String> deps1,deps2;
3087 algorithm
3088 ✗ (_,deps1) := node1;
3089 ✗ (_,deps2) := node2;
3090 ✗ cmp := listLength(deps1) >= listLength(deps2);
3091 end compareNumberOfDependencies;
3092
3093 protected function compareDependencyNode
3094 input tuple<String,list<String>> node1;
3095 input tuple<String,list<String>> node2;
3096 output Boolean cmp;
3097 protected
3098 String s1,s2;
3099 algorithm
3100 ✗ (s1,_) := node1;
3101 ✗ (s2,_) := node2;
3102 ✗ cmp := Util.strcmpBool(s1,s2);
3103 end compareDependencyNode;
3104
3105 protected function dependencyString
3106 input tuple<String,list<String>> deps;
3107 output String str;
3108 protected
3109 list<String> strs;
3110 algorithm
3111 ✗ (str,strs) := deps;
3112 ✗ str := str + " (" + intString(listLength(strs)) + "): " + stringDelimitList(strs, ",");
3113 end dependencyString;
3114
3115 protected function transitiveDependencyString
3116 input tuple<String,list<String>> deps;
3117 output String str;
3118 protected
3119 list<String> strs;
3120 algorithm
3121 ✗ (str,strs) := deps;
3122 ✗ str := intString(listLength(strs)) + ": ("+str+") " + stringDelimitList(strs, ",");
3123 end transitiveDependencyString;
3124
3125 protected function containsPublicInterface
3126 input SCode.Element elt;
3127 output Boolean b;
3128 algorithm
3129 b := match elt
3130 local
3131 list<SCode.Element> elts;
3132 String name;
3133 case SCode.CLASS(restriction=SCode.R_PACKAGE(), encapsulatedPrefix=SCode.ENCAPSULATED(), classDef=SCode.PARTS(elementLst=elts))
3134 ✗ then List.any(elts, containsPublicInterface2);
3135 else
3136 algorithm
3137 ✗ name := SCodeUtil.elementName(elt);
3138 ✗ name := "CevalScript.containsPublicInterface failed: " + name;
3139 ✗ Error.addMessage(Error.INTERNAL_ERROR, {name});
3140 ✗ then fail();
3141 end match;
3142 end containsPublicInterface;
3143
3144 protected function containsPublicInterface2
3145 "If the package contains a public type or constant, we depend on this package also through other modules"
3146 input SCode.Element elt;
3147 output Boolean b;
3148 algorithm
3149 b := match elt
3150 local
3151 case SCode.IMPORT() then false;
3152 case SCode.EXTENDS() then false;
3153 case SCode.CLASS(restriction=SCode.R_FUNCTION(_)) then false;
3154 case SCode.COMPONENT(prefixes=SCode.PREFIXES(visibility=SCode.PUBLIC()))
3155 algorithm
3156 // print("public component " + name + ": ");
3157 then true;
3158 case SCode.CLASS(prefixes=SCode.PREFIXES(visibility=SCode.PUBLIC()))
3159 algorithm
3160 // print("public class " + name + ": ");
3161 then true;
3162 else false;
3163 end match;
3164 end containsPublicInterface2;
3165
3166 protected function containsImport
3167 input SCode.Element elt;
3168 input SCode.Visibility visibility;
3169 output Boolean b;
3170 algorithm
3171 b := match elt
3172 local
3173 list<SCode.Element> elts;
3174 String name;
3175 case SCode.CLASS(restriction=SCode.R_PACKAGE(), encapsulatedPrefix=SCode.ENCAPSULATED(), classDef=SCode.PARTS(elementLst=elts))
3176 ✗ then List.exist1(elts, containsImport2, visibility);
3177 else
3178 algorithm
3179 ✗ name := SCodeUtil.elementName(elt);
3180 ✗ name := "CevalScript.containsPublicInterface failed: " + name;
3181 ✗ Error.addMessage(Error.INTERNAL_ERROR, {name});
3182 ✗ then fail();
3183 end match;
3184 end containsImport;
3185
3186 protected function containsImport2
3187 "If the package contains a public type or constant, we depend on this package also through other modules"
3188 input SCode.Element elt;
3189 input SCode.Visibility visibility;
3190 output Boolean b;
3191 algorithm
3192 b := match (elt,visibility)
3193 local
3194 case (SCode.IMPORT(visibility=SCode.PUBLIC()),SCode.PUBLIC()) then true;
3195 case (SCode.IMPORT(visibility=SCode.PROTECTED()),SCode.PROTECTED()) then true;
3196 else false;
3197 end match;
3198 end containsImport2;
3199
3200 protected function printInterfaceString
3201 input SCode.Element elt;
3202 protected
3203 String str;
3204 algorithm
3205 ✗ SCode.CLASS(name=str) := elt;
3206 ✗ print(str + ": " + boolString(containsPublicInterface(elt)) + "\n");
3207 end printInterfaceString;
3208
3209 protected function writeModuleDepends
3210 input SCode.Element cl;
3211 input String prefix;
3212 input String suffix;
3213 input list<tuple<String,list<String>>> deps;
3214 output String str;
3215 algorithm
3216 str := matchcontinue cl
3217 local
3218 String name,tmp1;
3219 list<String> allDepends,protectedDepends,tmp2;
3220 list<SCode.Element> elts;
3221 SourceInfo info;
3222 case SCode.CLASS(name=name, classDef=SCode.PARTS(elementLst=elts), info = SOURCEINFO())
3223 algorithm
3224 ✗ protectedDepends := List.map(List.select(elts,SCodeUtil.elementIsProtectedImport),importDependency);
3225 ✗ protectedDepends := List.select(protectedDepends, isNotBuiltinImport);
3226 ✗ _::allDepends := Graph.allReachableNodes((name::protectedDepends,{}),deps,stringEq);
3227 ✗ allDepends := List.map1r(allDepends, stringAppend, prefix);
3228 ✗ allDepends := List.map1(allDepends, stringAppend, ".interface.mo");
3229 ✗ str := prefix + name + suffix + ": $(RELPATH_" + name + ") " + stringDelimitList(allDepends," ");
3230 then str;
3231 case SCode.CLASS(name=name, classDef=SCode.PARTS(elementLst=elts), info=info)
3232 algorithm
3233 ✗ protectedDepends := List.map(List.select(elts,SCodeUtil.elementIsProtectedImport),importDependency);
3234 ✗ protectedDepends := List.select(protectedDepends, isNotBuiltinImport);
3235 ✗ allDepends := list(Util.tuple21(e) for e in deps);
3236 ✗ for d in protectedDepends loop
3237 ✗ if not listMember(d, allDepends) then
3238 ✗ Error.addSourceMessage(Error.GENERATE_SEPARATE_CODE_DEPENDENCIES_FAILED_UNKNOWN_PACKAGE, {name,name,d}, info);
3239 ✗ fail();
3240 end if;
3241 end for;
3242 ✗ for dep in deps loop
3243 ✗ (tmp1,tmp2) := dep;
3244 ✗ for d in tmp2 loop
3245 ✗ if not listMember(d, allDepends) then
3246 ✗ Error.addSourceMessage(Error.GENERATE_SEPARATE_CODE_DEPENDENCIES_FAILED_UNKNOWN_PACKAGE, {name,tmp1,d}, info);
3247 ✗ fail();
3248 end if;
3249 end for;
3250 end for;
3251 ✗ then fail();
3252 case SCode.CLASS(name=name,info=info)
3253 algorithm
3254 ✗ Error.addSourceMessage(Error.GENERATE_SEPARATE_CODE_DEPENDENCIES_FAILED, {name}, info);
3255 ✗ then fail();
3256 end matchcontinue;
3257 end writeModuleDepends;
3258
3259 protected function isNotBuiltinImport
3260 input String module;
3261 output Boolean b = module <> "MetaModelica";
3262 end isNotBuiltinImport;
3263
3264 protected function getTypeNameIdent
3265 input Values.Value val;
3266 output String str;
3267 algorithm
3268 ✗ Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT(str))) := val;
3269 end getTypeNameIdent;
3270
3271 protected function getChangedClass
3272 input SCode.Element elt;
3273 input String suffix;
3274 output String name;
3275 algorithm
3276 name := match elt
3277 local
3278 String fileName;
3279 case SCode.CLASS(name=name,info=SOURCEINFO()) guard not System.regularFileExists(name + suffix)
3280 then name;
3281 case SCode.CLASS(name=name,info=SOURCEINFO(fileName=fileName))
3282 algorithm
3283 ✗ true := System.fileIsNewerThan(fileName, name + suffix);
3284 then name;
3285 end match;
3286 end getChangedClass;
3287
3288 protected function isChanged
3289 input tuple<String,list<String>> node;
3290 input HashSetString.HashSet hs;
3291 output Boolean b;
3292 protected
3293 String str;
3294 list<String> strs;
3295 algorithm
3296 ✗ (str,strs) := node;
3297 ✗ b := List.exist1(str::strs,BaseHashSet.has,hs);
3298 // print(str + ": " + boolString(b) + "\n");
3299 end isChanged;
3300
3301 protected function reloadClass
3302 input String filename;
3303 input String encoding;
3304 protected
3305 Absyn.Program newp;
3306 algorithm
3307 ✗ newp := Parser.parse(filename,encoding); /* Don't use the classloader since that can pull in entire directory structures. We only want to reload one single file. */
3308 ✗ newp := ProgramUtil.updateProgram(newp, SymbolTable.getAbsyn());
3309 ✗ SymbolTable.setAbsyn(newp);
3310 end reloadClass;
3311
3312 public function translateFunctions "
3313 Entry point to translate Modelica/MetaModelica functions to C functions.
3314 Called from other places in the compiler."
3315 input Absyn.Program program;
3316 input String name;
3317 input Option<DAE.Function> optMainFunction;
3318 input list<DAE.Function> idaeElements;
3319 input list<DAE.Type> metarecordTypes;
3320 input list<String> inIncludes;
3321 algorithm
3322 142 setGlobalRoot(Global.optionSimCode, NONE());
3323
3324 () := match (optMainFunction, idaeElements, inIncludes)
3325 local
3326 DAE.Function daeMainFunction;
3327 SimCodeFunction.Function mainFunction;
3328 list<SimCodeFunction.Function> fns;
3329 list<String> includes, libs, libPaths,includeDirs;
3330 SimCodeFunction.MakefileParams makefileParams;
3331 SimCodeFunction.FunctionCode fnCode;
3332 list<SimCodeFunction.RecordDeclaration> extraRecordDecls;
3333 list<DAE.Exp> literals;
3334 list<DAE.Function> daeElements;
3335 Tpl.Text midCode;
3336 list<MidCode.Function> midfuncs;
3337 case (SOME(daeMainFunction), daeElements, includes)
3338 algorithm
3339 // Create FunctionCode
3340 142 (daeElements,literals) := SimCodeFunctionUtil.findLiterals(daeMainFunction::daeElements);
3341
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 142 times.
142 (mainFunction::fns, extraRecordDecls, includes, includeDirs, libs, libPaths) := SimCodeFunctionUtil.elaborateFunctions(program, daeElements, metarecordTypes, literals, includes);
3342 142 SimCodeFunctionUtil.checkValidMainFunction(name, mainFunction);
3343 142 makefileParams := SimCodeFunctionUtil.createMakefileParams(includeDirs, libs, libPaths, true);
3344 142 fnCode := SimCodeFunction.FUNCTIONCODE(name, SOME(mainFunction), fns, literals, includes, makefileParams, extraRecordDecls);
3345 142 SimCodeFunctionUtil.setTrivialRecords(extraRecordDecls);
3346
3347
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 142 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
142 if Config.simCodeTarget() == "wasm-jit" then
3348 ✗ CodegenWasmJitFunctions.translateFunctions(fnCode);
3349 elseif Config.simCodeTarget() == "MidC" then
3350 ✗ Tpl.tplString(CodegenCFunctions.translateFunctionHeaderFiles, fnCode);
3351 ✗ midfuncs := DAEToMid.DAEFunctionsToMid(mainFunction::fns);
3352 ✗ midCode := Tpl.tplCallWithFailError(CodegenMidToC.genProgram, MidCode.PROGRAM(name, midfuncs));
3353 ✗ Tpl.textFileConvertLines(midCode, name + ".c");
3354 else
3355 142 Tpl.tplString(CodegenCFunctions.translateFunctions, fnCode);
3356 end if;
3357 then
3358 ();
3359 case (NONE(), daeElements, includes)
3360 algorithm
3361 // Create FunctionCode
3362 ✗ (daeElements,literals) := SimCodeFunctionUtil.findLiterals(daeElements);
3363 ✗ (fns, extraRecordDecls, includes, includeDirs, libs, libPaths) := SimCodeFunctionUtil.elaborateFunctions(program, daeElements, metarecordTypes, literals, includes);
3364 ✗ makefileParams := SimCodeFunctionUtil.createMakefileParams(includeDirs, libs, libPaths, true);
3365 // remove OpenModelica.threadData.ThreadData
3366 ✗ fns := removeThreadDataFunction(fns, {});
3367 ✗ extraRecordDecls := removeThreadDataRecord(extraRecordDecls, {});
3368 ✗ fnCode := SimCodeFunction.FUNCTIONCODE(name, NONE(), fns, literals, includes, makefileParams, extraRecordDecls);
3369 ✗ SimCodeFunctionUtil.setTrivialRecords(extraRecordDecls);
3370
3371 ✗ if Config.simCodeTarget() == "MidC" then
3372 ✗ Tpl.tplString(CodegenCFunctions.translateFunctionHeaderFiles, fnCode);
3373 ✗ midfuncs := DAEToMid.DAEFunctionsToMid(fns);
3374 ✗ midCode := Tpl.tplCallWithFailError(CodegenMidToC.genProgram, MidCode.PROGRAM(name, midfuncs));
3375 ✗ Tpl.textFileConvertLines(midCode, name + ".c");
3376 else
3377 ✗ Tpl.tplString(CodegenCFunctions.translateFunctions, fnCode);
3378 end if;
3379 then
3380 ();
3381
3382 end match;
3383 end translateFunctions;
3384
3385 protected function removeThreadDataRecord
3386 "remove OpenModelica.threadData.ThreadData
3387 as is already defined in openmodelica.h"
3388 input list<SimCodeFunction.RecordDeclaration> inRecs;
3389 input list<SimCodeFunction.RecordDeclaration> inAcc;
3390 output list<SimCodeFunction.RecordDeclaration> outRecs;
3391 algorithm
3392 outRecs := match inRecs
3393 local
3394 list<SimCodeFunction.RecordDeclaration> acc, rest;
3395 SimCodeFunction.RecordDeclaration r;
3396
3397 ✗ case {} then listReverse(inAcc);
3398
3399 case SimCodeFunction.RECORD_DECL_FULL(name = "OpenModelica_threadData_ThreadData")::rest
3400 algorithm
3401 ✗ acc := removeThreadDataRecord(rest, inAcc);
3402 then
3403 acc;
3404
3405 case SimCodeFunction.RECORD_DECL_DEF(path = Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("threadData",Absyn.IDENT("ThreadData"))))::rest
3406 algorithm
3407 ✗ acc := removeThreadDataRecord(rest, inAcc);
3408 then
3409 acc;
3410
3411 case r::rest
3412 algorithm
3413 ✗ acc := removeThreadDataRecord(rest, r::inAcc);
3414 then
3415 acc;
3416
3417 end match;
3418 end removeThreadDataRecord;
3419
3420 protected function removeThreadDataFunction
3421 "remove OpenModelica.threadData.ThreadData
3422 as is already defined in openmodelica.h"
3423 input list<SimCodeFunction.Function> inFuncs;
3424 input list<SimCodeFunction.Function> inAcc;
3425 output list<SimCodeFunction.Function> outFuncs;
3426 algorithm
3427 outFuncs := match inFuncs
3428 local
3429 list<SimCodeFunction.Function> acc, rest;
3430 SimCodeFunction.Function f;
3431
3432 ✗ case {} then listReverse(inAcc);
3433
3434 case SimCodeFunction.RECORD_CONSTRUCTOR(name = Absyn.FULLYQUALIFIED(Absyn.QUALIFIED("OpenModelica",Absyn.QUALIFIED("threadData",Absyn.IDENT("ThreadData")))))::rest
3435 algorithm
3436 ✗ acc := removeThreadDataFunction(rest, inAcc);
3437 then
3438 acc;
3439
3440 case f::rest
3441 algorithm
3442 ✗ acc := removeThreadDataFunction(rest, f::inAcc);
3443 then
3444 acc;
3445
3446 end match;
3447 end removeThreadDataFunction;
3448
3449 protected function unZipEncryptedPackageAndCheckFile
3450 input String inWorkdir;
3451 input String filename;
3452 input Boolean skipUnzip;
3453 output Boolean success;
3454 output String outFilename;
3455 protected
3456 String workdir, s1, s2, s3, filename_1, filename1, filename2, filename3, filename4, str, str1, str2, str3, str4, cmd, cmdPrefix;
3457 Boolean isWindows = Autoconf.os == "Windows_NT";
3458 algorithm
3459 success := false;
3460 outFilename := "";
3461
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (System.regularFileExists(filename)) then
3462
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (StringUtil.endsWith(filename, ".mol")) then
3463
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 workdir := if System.directoryExists(inWorkdir) then inWorkdir else System.pwd();
3464 // use ripunzip (https://github.com/google/ripunzip) on Windows as is twice as fast
3465 // TODO on Linux we should check if it is in the path
3466 cmdPrefix := if isWindows then "ripunzip.exe -q unzip-file -d " else "unzip -q -o -d ";
3467 4 cmd := cmdPrefix + "\"" + workdir + "\" \"" + filename + "\"";
3468
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
4 if (skipUnzip or 0 == System.systemCall(cmd)) then
3469 4 s1 := System.basename(filename);
3470 4 s2 := Util.removeLast4Char(s1);
3471 4 s3 := listGet(Util.stringSplitAtChar(s2," "),1);
3472 // possible .moc files to look for
3473 4 filename1 := workdir + "/" + s2 + "/package.moc";
3474 4 filename2 := workdir + "/" + s2 + "/" + s2 + ".moc";
3475 4 filename3 := workdir + "/" + s3 + "/package.moc";
3476 4 filename4 := workdir + "/" + s3 + "/" + s3 + ".moc";
3477
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if System.regularFileExists(filename1) then
3478 filename_1 := filename1;
3479 elseif System.regularFileExists(filename2) then
3480 filename_1 := filename2;
3481 elseif System.regularFileExists(filename3) then
3482 filename_1 := filename3;
3483 else
3484 filename_1 := filename4;
3485 end if;
3486 // possible .mo files to look for
3487 4 str1 := workdir + "/" + s2 + "/package.mo";
3488 4 str2 := workdir + "/" + s2 + "/" + s2 + ".mo";
3489 4 str3 := workdir + "/" + s3 + "/package.mo";
3490 4 str4 := workdir + "/" + s3 + "/" + s3 + ".mo";
3491
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if System.regularFileExists(str1) then
3492 str := str1;
3493 elseif System.regularFileExists(str2) then
3494 str := str2;
3495 elseif System.regularFileExists(str3) then
3496 str := str3;
3497 else
3498 str := str4;
3499 end if;
3500 // check if .mol contains .moc or .mo files
3501
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 filename_1 := if System.regularFileExists(filename_1) then filename_1 else str;
3502
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (System.regularFileExists(filename_1)) then
3503 success := true;
3504 outFilename := filename_1;
3505 else
3506 ✗ Error.addMessage(Error.PACKAGE_FILE_NOT_FOUND_ERROR, {filename1, filename2, filename3, filename4, str1, str2, str3, str4});
3507 end if;
3508 else
3509 ✗ Error.addMessage(Error.UNABLE_TO_UNZIP_FILE, {filename});
3510 end if;
3511 else
3512 ✗ Error.addMessage(Error.EXPECTED_ENCRYPTED_PACKAGE, {filename});
3513 end if;
3514 else
3515 ✗ Error.addMessage(Error.FILE_NOT_FOUND_ERROR, {filename});
3516 end if;
3517 end unZipEncryptedPackageAndCheckFile;
3518
3519 function listClass
3520 input list<Values.Value> args;
3521 output Values.Value res;
3522 protected
3523 String str, name;
3524 Absyn.Program p;
3525 SCode.Program scodeP;
3526 Absyn.Class absynClass;
3527 SCode.Element cl;
3528 Absyn.Path path, className;
3529 Boolean interface_only, short_only;
3530 constant SCodeDump.SCodeDumpOptions dumpOpt =
3531 SCodeDump.OPTIONS(true,false,true,true,true,true,true,true,true);
3532 algorithm
3533 str := matchcontinue args
3534 // handle encryption
3535 case _
3536 algorithm
3537 // if AST contains encrypted class show nothing
3538 98 p := SymbolTable.getAbsyn();
3539
1/2
✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
98 true := Interactive.astContainsEncryptedClass(p);
3540 ✗ Error.addMessage(Error.ACCESS_ENCRYPTED_PROTECTED_CONTENTS, {});
3541 then
3542 "";
3543
3544 case {Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT("AllLoadedClasses"))),
3545 Values.BOOL(false), Values.BOOL(false), Values.ENUM_LITERAL(name=path)}
3546 then
3547 match AbsynUtil.pathLastIdent(path)
3548 20 case "Absyn" then Dump.unparseStr(SymbolTable.getAbsyn(), false);
3549 ✗ case "SCode" then SCodeDump.programStr(SymbolTable.getSCode());
3550 ✗ case "MetaModelicaInterface" then SCodeDump.programStr(SymbolTable.getSCode(), dumpOpt);
3551 ✗ case "Internal" then System.anyStringCode(SymbolTable.getAbsyn());
3552 else "";
3553 end match;
3554
3555 case {Values.CODE(Absyn.C_TYPENAME(className)), Values.BOOL(interface_only),
3556 Values.BOOL(short_only), Values.ENUM_LITERAL(name=path)}
3557 algorithm
3558
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 78 times.
78 false := valueEq(Absyn.IDENT("AllLoadedClasses"),className);
3559 78 p := SymbolTable.getAbsyn();
3560 78 scodeP := SymbolTable.getSCode();
3561 78 absynClass := ProgramUtil.getPathedClassInProgram(className, p);
3562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 absynClass := if interface_only then AbsynUtil.getFunctionInterface(absynClass) else absynClass;
3563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 absynClass := if short_only then AbsynUtil.getShortClass(absynClass) else absynClass;
3564 78 p := Absyn.PROGRAM({absynClass},Absyn.TOP());
3565 78 cl := FBuiltin.getElementWithPathCheckBuiltin(scodeP, className);
3566 then
3567 match AbsynUtil.pathLastIdent(path)
3568 78 case "Absyn" then Dump.unparseStr(p, false);
3569 ✗ case "SCode" then SCodeDump.unparseElementStr(cl);
3570 ✗ case "MetaModelicaInterface" then SCodeDump.unparseElementStr(cl, dumpOpt);
3571 ✗ case "Internal" then System.anyStringCode(p);
3572 else "";
3573 end match;
3574
3575 else "";
3576 end matchcontinue;
3577
3578 98 res := Values.STRING(str);
3579 end listClass;
3580
3581 function listFile
3582 input list<Values.Value> args;
3583 output Values.Value res;
3584 protected
3585 String str;
3586 Absyn.Path path, className;
3587 Boolean nested;
3588 Access access;
3589 Absyn.Class absynClass;
3590 Absyn.Restriction restriction;
3591 algorithm
3592 str := matchcontinue args
3593 case {Values.CODE(Absyn.C_TYPENAME(className)), Values.BOOL(nested)}
3594 algorithm
3595 path := match className
3596 ✗ case Absyn.FULLYQUALIFIED() then className.path;
3597 else className;
3598 end match;
3599 // handle encryption
3600 5 access := Interactive.checkAccessAnnotationAndEncryption(path, SymbolTable.getAbsyn());
3601 5 absynClass as Absyn.CLASS(restriction=restriction, info=SOURCEINFO(fileName=str)) := ProgramUtil.getPathedClassInProgram(className, SymbolTable.getAbsyn());
3602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 absynClass := if nested then absynClass else AbsynUtil.filterNestedClasses(absynClass);
3603 /* If the class has Access.packageText annotation or higher
3604 * If the class has Access.nonPackageText annotation or higher and class is not a package
3605 */
3606
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
5 if ((access >= Access.packageText) or ((access >= Access.nonPackageText) and not AbsynUtil.isPackageRestriction(restriction))) then
3607 2 str := Dump.unparseStr(Absyn.PROGRAM({absynClass}, match path case Absyn.IDENT() then Absyn.TOP(); else Absyn.WITHIN(AbsynUtil.stripLast(path)); end match), options=Dump.DUMPOPTIONS(str));
3608 else
3609 ✗ Error.addMessage(Error.ACCESS_ENCRYPTED_PROTECTED_CONTENTS, {});
3610 str := "";
3611 end if;
3612 then
3613 str;
3614
3615 else "";
3616 end matchcontinue;
3617
3618 5 res := Values.STRING(str);
3619 end listFile;
3620
3621 function getClassNames
3622 input list<Values.Value> args;
3623 output Values.Value res;
3624 protected
3625 Absyn.Path path;
3626 Boolean recursive, qualified, sort, builtin, protects, constants;
3627 Absyn.Program p;
3628 list<Absyn.Path> paths;
3629 algorithm
3630
16/32
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 15 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 15 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 15 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 15 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 15 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 15 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 15 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 15 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 15 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 15 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 15 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 15 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 15 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 15 times.
15 {Values.CODE(Absyn.C_TYPENAME(path)),
3631 Values.BOOL(recursive),
3632 Values.BOOL(qualified),
3633 Values.BOOL(sort),
3634 Values.BOOL(builtin),
3635 Values.BOOL(protects),
3636 Values.BOOL(constants)} := args;
3637
3638 15 p := SymbolTable.getAbsyn();
3639
3640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if builtin then
3641 ✗ p := ProgramUtil.updateProgram(p, FBuiltin.getInitialFunctions());
3642 end if;
3643
3644
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 10 times.
15 if AbsynUtil.pathEqual(path, Absyn.IDENT("AllLoadedClasses")) then
3645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if recursive then
3646 ✗ (_, paths) := ProgramUtil.getClassNamesRecursive(NONE(), p, protects, constants, {});
3647 ✗ paths := listReverseInPlace(paths);
3648 else
3649 5 paths := Interactive.getTopClassnames(p);
3650 end if;
3651 else
3652
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 9 times.
10 if recursive then
3653 1 (_, paths) := ProgramUtil.getClassNamesRecursive(SOME(path), p, protects, constants, {});
3654 1 paths := listReverseInPlace(paths);
3655 else
3656 9 paths := Interactive.getClassnamesInPath(path, p, protects, constants);
3657
3658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if qualified then
3659 ✗ paths := list(AbsynUtil.joinPaths(path, p) for p in paths);
3660 end if;
3661 end if;
3662 end if;
3663
3664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if sort then
3665 ✗ paths := List.sort(paths, AbsynUtil.pathGe);
3666 end if;
3667
3668 15 res := ValuesMake.makeCodeTypeNameArray(paths);
3669 end getClassNames;
3670
3671 function checkSettings
3672 output Values.Value res;
3673 protected
3674 list<String> vars;
3675 String omhome, omlib, omcpath, systemPath, omdev, os, touch_file, usercflags;
3676 String workdir, uname, senddata, gcc, gccVersion, confcmd;
3677 Boolean omcfound, touch_res, rm_res, gcc_res;
3678 list<Values.Value> vals;
3679 algorithm
3680 vars := {"OPENMODELICAHOME",
3681 "OPENMODELICALIBRARY",
3682 "OMC_PATH",
3683 "SYSTEM_PATH",
3684 "OMDEV_PATH",
3685 "OMC_FOUND",
3686 "MODELICAUSERCFLAGS",
3687 "WORKING_DIRECTORY",
3688 "CREATE_FILE_WORKS",
3689 "REMOVE_FILE_WORKS",
3690 "OS",
3691 "SYSTEM_INFO",
3692 "RTLIBS",
3693 "C_COMPILER",
3694 "C_COMPILER_VERSION",
3695 "C_COMPILER_RESPONDING",
3696 "CONFIGURE_CMDLINE"};
3697 ✗ omhome := Settings.getInstallationDirectoryPath();
3698 ✗ omlib := Settings.getModelicaPath(Testsuite.isRunning());
3699 ✗ omcpath := omhome + "/bin/omc" + Autoconf.exeExt;
3700 ✗ systemPath := Util.makeValueOrDefault(System.readEnv,"PATH","");
3701 ✗ omdev := Util.makeValueOrDefault(System.readEnv,"OMDEV","");
3702 ✗ omcfound := System.regularFileExists(omcpath);
3703 os := Autoconf.os;
3704 touch_file := "omc.checksettings.create_file_test";
3705 ✗ usercflags := Util.makeValueOrDefault(System.readEnv,"MODELICAUSERCFLAGS","");
3706 ✗ workdir := System.pwd();
3707 ✗ touch_res := 0 == System.systemCall("touch " + touch_file, "");
3708 ✗ System.systemCall("uname -a", touch_file);
3709 ✗ uname := System.readFile(touch_file);
3710 ✗ rm_res := 0 == System.systemCall("rm " + touch_file, "");
3711 // _ = System.platform();
3712 senddata := Autoconf.ldflags_runtime;
3713 ✗ gcc := System.getCCompiler();
3714 ✗ System.systemCall("rm -f " + touch_file, "");
3715 ✗ gcc_res := 0 == System.systemCall(gcc + " --version", touch_file);
3716 ✗ gccVersion := System.readFile(touch_file);
3717 ✗ System.systemCall("rm -f " + touch_file, "");
3718 confcmd := Autoconf.configureCommandLine;
3719 ✗ vals := {Values.STRING(omhome),
3720 Values.STRING(omlib),
3721 Values.STRING(omcpath),
3722 Values.STRING(systemPath),
3723 Values.STRING(omdev),
3724 Values.BOOL(omcfound),
3725 Values.STRING(usercflags),
3726 Values.STRING(workdir),
3727 Values.BOOL(touch_res),
3728 Values.BOOL(rm_res),
3729 Values.STRING(os),
3730 Values.STRING(uname),
3731 Values.STRING(senddata),
3732 Values.STRING(gcc),
3733 Values.STRING(gccVersion),
3734 Values.BOOL(gcc_res),
3735 Values.STRING(confcmd)};
3736
3737 ✗ res := Values.RECORD(Absyn.IDENT("OpenModelica.Scripting.CheckSettingsResult"), vals, vars, -1);
3738 end checkSettings;
3739
3740 function generateSeparateCodeDependenciesMakefile
3741 input list<Values.Value> args;
3742 output Values.Value res;
3743 protected
3744 SCode.Program sp;
3745 list<String> names, strs;
3746 list<tuple<String,list<String>>> deps;
3747 String filename, prefix, suffix;
3748 algorithm
3749 try
3750 ✗ {Values.STRING(filename),Values.STRING(prefix),Values.STRING(suffix)} := args;
3751 ✗ sp := SymbolTable.getSCode();
3752 ✗ names := List.filterMap(sp,SCodeUtil.getElementName);
3753 ✗ deps := Graph.buildGraph(names,buildDependencyGraphPublicImports,sp);
3754 ✗ strs := List.map3(sp,writeModuleDepends,prefix,suffix,deps);
3755 ✗ System.writeFile(filename,stringDelimitList(strs,"\n"));
3756 res := Values.BOOL(true);
3757 else
3758 res := Values.BOOL(false);
3759 end try;
3760 end generateSeparateCodeDependenciesMakefile;
3761
3762 function generateSeparateCodeDependencies
3763 input list<Values.Value> args;
3764 output Values.Value res;
3765 protected
3766 String suffix;
3767 SCode.Program sp;
3768 list<String> names, namesPublic, namesChanged, fileNames;
3769 list<tuple<String,list<String>>> deps, depstransitive, depstransposed,
3770 depstransposedtransitive, depsmerged, depschanged;
3771 HashSetString.HashSet hashSetString;
3772 algorithm
3773 try
3774 ✗ {Values.STRING(suffix)} := args;
3775 ✗ sp := SymbolTable.getSCode();
3776 ✗ names := List.filterMap(sp,SCodeUtil.getElementName);
3777
3778 ✗ deps := Graph.buildGraph(names,buildDependencyGraph,sp);
3779 ✗ namesPublic := List.map(List.select(sp, containsPublicInterface), SCodeUtil.getElementName);
3780 ✗ namesChanged := List.filterMap1(sp,getChangedClass,suffix);
3781 ✗ hashSetString := HashSetString.emptyHashSet();
3782 ✗ hashSetString := List.fold(namesChanged,BaseHashSet.add,hashSetString);
3783 // print("namesChanged: " + stringDelimitList(namesChanged, ",") + "\n");
3784
3785 ✗ depstransposed := Graph.transposeGraph(Graph.emptyGraph(names),deps,stringEq);
3786 ✗ depstransposedtransitive := Graph.buildGraph(namesPublic,buildTransitiveDependencyGraph,depstransposed);
3787 // depstransposedtransitive = List.sort(depstransposed, compareNumberOfDependencies);
3788
3789 ✗ depstransitive := Graph.transposeGraph(Graph.emptyGraph(names),depstransposedtransitive,stringEq);
3790 ✗ depstransitive := List.sort(depstransitive, compareNumberOfDependencies);
3791
3792 ✗ depsmerged := Graph.merge(deps,depstransitive,stringEq,compareDependencyNode);
3793 // depsmerged = List.sort(depsmerged, compareNumberOfDependencies);
3794
3795 /*
3796 print("Total number of modules: " + intString(listLength(depsmerged)) + "\n");
3797 str = stringDelimitList(List.map(depsmerged, transitiveDependencyString), "\n");
3798 print(str + "\n");
3799 */
3800
3801 ✗ depschanged := List.select1(depsmerged,isChanged,hashSetString);
3802 ✗ names := List.map(depschanged, Util.tuple21);
3803 // print("Files to recompile (" + intString(listLength(depschanged)) + "): " + stringDelimitList(names, ",") + "\n");
3804 ✗ fileNames := List.map1(names, stringAppend, suffix);
3805
3806 ✗ for f in fileNames loop
3807 ✗ System.removeFile(f);
3808 end for;
3809
3810 ✗ res := ValuesMake.makeArray(List.map(names,ValuesMake.makeString));
3811 else
3812 res := Values.META_FAIL();
3813 end try;
3814 end generateSeparateCodeDependencies;
3815
3816 function generateSeparateCode
3817 input list<Values.Value> args;
3818 input FCore.Cache cache;
3819 input FCore.Graph env;
3820 output Values.Value res;
3821 output FCore.Cache outCache = cache;
3822 protected
3823 Values.Value v;
3824 Boolean b;
3825 Absyn.Program p;
3826 SCode.Program sp;
3827 String name;
3828 SCode.Element cl;
3829 algorithm
3830 res := matchcontinue args
3831 case {v, Values.BOOL(b)}
3832 algorithm
3833 ✗ p := SymbolTable.getAbsyn();
3834 ✗ sp := SymbolTable.getSCode();
3835 ✗ name := getTypeNameIdent(v);
3836 ✗ setGlobalRoot(Global.instOnlyForcedFunctions,SOME(true));
3837 ✗ cl := List.getMemberOnTrue(name, sp, SCodeUtil.isClassNamed);
3838 ✗ outCache := generateFunctions(cache,env,p,sp,{cl},b);
3839 ✗ setGlobalRoot(Global.instOnlyForcedFunctions,NONE());
3840 then
3841 Values.BOOL(true);
3842
3843 case {v, Values.BOOL(_)}
3844 algorithm
3845 ✗ sp := SymbolTable.getSCode();
3846 ✗ name := getTypeNameIdent(v);
3847 ✗ false := List.isMemberOnTrue(name, sp, SCodeUtil.isClassNamed);
3848 ✗ Error.addMessage(Error.LOOKUP_ERROR, {name,"<TOP>"});
3849 ✗ then
3850 fail();
3851
3852 else
3853 algorithm
3854 ✗ setGlobalRoot(Global.instOnlyForcedFunctions,NONE());
3855 then
3856 Values.BOOL(false);
3857
3858 end matchcontinue;
3859 end generateSeparateCode;
3860
3861
3862 public function getImportedNames
3863 input Absyn.Class inClass;
3864 output list<Values.Value> outPublicImports;
3865 output list<Values.Value> outProtectedImports;
3866 protected
3867 String ident;
3868 list<Absyn.Import> pub_imports_list , pro_imports_list;
3869 algorithm
3870 ✗ (pub_imports_list , pro_imports_list) := getImportList(inClass);
3871
3872 outPublicImports := {};
3873 ✗ for imp in pub_imports_list loop
3874 ✗ ident := AbsynUtil.pathFirstIdent(AbsynUtil.importPath(imp));
3875 ✗ if ident <> "MetaModelica" then
3876 ✗ outPublicImports := Values.STRING(ident)::outPublicImports;
3877 end if;
3878 end for;
3879
3880 outProtectedImports := {};
3881 ✗ for imp in pro_imports_list loop
3882 ✗ ident := AbsynUtil.pathFirstIdent(AbsynUtil.importPath(imp));
3883 ✗ if ident <> "MetaModelica" then
3884 ✗ outProtectedImports := Values.STRING(ident)::outProtectedImports;
3885 end if;
3886 end for;
3887 end getImportedNames;
3888
3889 public function getImportList
3890 "Counts the number of Import sections in a class."
3891 input Absyn.Class inClass;
3892 input output list<Absyn.Import> pub_imports_list = {};
3893 input output list<Absyn.Import> pro_imports_list = {};
3894 algorithm
3895 ✗ for part in AbsynUtil.getClassPartsInClass(inClass) loop
3896 ✗ (pub_imports_list, pro_imports_list) := getImportsInClassPart(part, pub_imports_list, pro_imports_list);
3897 end for;
3898
3899 ✗ pub_imports_list := listReverseInPlace(pub_imports_list);
3900 ✗ pro_imports_list := listReverseInPlace(pro_imports_list);
3901 end getImportList;
3902
3903 protected function getImportsInClassPart
3904 input Absyn.ClassPart part;
3905 input output list<Absyn.Import> pub_imports_list;
3906 input output list<Absyn.Import> pro_imports_list;
3907 algorithm
3908 () := match part
3909 case Absyn.PUBLIC()
3910 algorithm
3911 ✗ for elem in part.contents loop
3912 ✗ pub_imports_list := getImportsInElementItem(elem, pub_imports_list);
3913 end for;
3914 then
3915 ();
3916
3917 case Absyn.PROTECTED()
3918 algorithm
3919 ✗ for elem in part.contents loop
3920 ✗ pro_imports_list := getImportsInElementItem(elem, pro_imports_list);
3921 end for;
3922 then
3923 ();
3924
3925 else ();
3926 end match;
3927 end getImportsInClassPart;
3928
3929 protected function getImportsInElementItem
3930 "Helper function to getImportCount"
3931 input Absyn.ElementItem item;
3932 input output list<Absyn.Import> imports_list;
3933 algorithm
3934 () := match item
3935 local
3936 Absyn.Import import_;
3937
3938 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.IMPORT(import_ = import_)))
3939 algorithm
3940 imports_list := import_::imports_list;
3941 then
3942 ();
3943
3944 else ();
3945 end match;
3946 end getImportsInElementItem;
3947
3948 protected function getMMfileTotalDependencies
3949 input String in_package_name;
3950 input String public_imports_dir;
3951 output list<String> total_pub_imports = {};
3952 protected
3953 Absyn.Class package_class;
3954 list<Absyn.Import> pub_imports_list , pro_imports_list;
3955 String imp_ident;
3956 algorithm
3957 ✗ package_class := ProgramUtil.getPathedClassInProgram(Absyn.IDENT(in_package_name), SymbolTable.getAbsyn());
3958
3959 ✗ (pub_imports_list , pro_imports_list) := getImportList(package_class);
3960
3961 ✗ for imp in pub_imports_list loop
3962 ✗ imp_ident := AbsynUtil.pathFirstIdent(AbsynUtil.importPath(imp));
3963 ✗ if imp_ident <> "MetaModelica" then
3964 ✗ total_pub_imports := getMMfilePublicDependencies(imp_ident, public_imports_dir, total_pub_imports);
3965 end if;
3966 end for;
3967
3968 ✗ for imp in pro_imports_list loop
3969 ✗ imp_ident := AbsynUtil.pathFirstIdent(AbsynUtil.importPath(imp));
3970 ✗ if imp_ident <> "MetaModelica" then
3971 ✗ total_pub_imports := getMMfilePublicDependencies(imp_ident, public_imports_dir, total_pub_imports);
3972 end if;
3973 end for;
3974
3975 end getMMfileTotalDependencies;
3976
3977 protected function getMMfilePublicDependencies
3978 input String in_package_name;
3979 input String public_imports_dir;
3980 input output list<String> packages;
3981 protected
3982 String dep_public_imports_file, pub_imports_total;
3983 algorithm
3984 ✗ if listMember(in_package_name, packages) then
3985 ✗ return;
3986 end if;
3987
3988 packages := in_package_name::packages;
3989
3990 ✗ dep_public_imports_file := public_imports_dir + "/" + in_package_name + ".public.imports";
3991 ✗ if not System.regularFileExists(dep_public_imports_file) then
3992 ✗ Error.addInternalError("getMMfileTotalDependencies: missing dependency file " + dep_public_imports_file
3993 + " — the module " + in_package_name + " is imported (transitively) but is not part of the build. "
3994 + "Add its source file to the build configuration.", sourceInfo());
3995 ✗ fail();
3996 end if;
3997 ✗ pub_imports_total := System.readFile(dep_public_imports_file);
3998
3999 ✗ for pub_imp in System.strtok(pub_imports_total, ";") loop
4000 ✗ packages := getMMfilePublicDependencies(pub_imp, public_imports_dir, packages);
4001 end for;
4002
4003 end getMMfilePublicDependencies;
4004
4005 annotation(__OpenModelica_Interface="backend_main");
4006 end CevalScript;
4007