OMCompiler/Compiler/Main/Main.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 Main | ||
| 37 | " file: Main.mo | ||
| 38 | package: Main | ||
| 39 | description: Modelica main program | ||
| 40 | |||
| 41 | |||
| 42 | This is the main program in the Modelica specification. | ||
| 43 | It either translates a file given as a command line argument | ||
| 44 | or starts a server loop communicating through ZeroMQ or sockets" | ||
| 45 | |||
| 46 | protected | ||
| 47 | import Absyn; | ||
| 48 | import ProgramUtil; | ||
| 49 | import AbsynJLDumpTpl; | ||
| 50 | import AbsynUtil; | ||
| 51 | import Autoconf; | ||
| 52 | import BackendInterfaceImplementation; | ||
| 53 | import CevalScript; | ||
| 54 | import CevalScriptBackend; | ||
| 55 | import ClockIndexes; | ||
| 56 | import Config; | ||
| 57 | import Debug; | ||
| 58 | import Dump; | ||
| 59 | import DumpGraphviz; | ||
| 60 | import Error; | ||
| 61 | import ErrorExt; | ||
| 62 | import ExecStat.{execStat,execStatReset}; | ||
| 63 | import FCore; | ||
| 64 | import FGraph; | ||
| 65 | import Flags; | ||
| 66 | import FlagsUtil; | ||
| 67 | import GCExt; | ||
| 68 | import Global; | ||
| 69 | import GlobalScript; | ||
| 70 | import Interactive; | ||
| 71 | import List; | ||
| 72 | import Parser; | ||
| 73 | import Print; | ||
| 74 | import Settings; | ||
| 75 | import Socket; | ||
| 76 | import StackOverflow; | ||
| 77 | import SymbolTable; | ||
| 78 | import System; | ||
| 79 | import Testsuite; | ||
| 80 | import TplMain; | ||
| 81 | import Util; | ||
| 82 | import ZeroMQ; | ||
| 83 | |||
| 84 | protected function makeDebugResult | ||
| 85 | input Flags.DebugFlag inFlag; | ||
| 86 | input String res; | ||
| 87 | output String res_1; | ||
| 88 | algorithm | ||
| 89 | res_1 := matchcontinue inFlag | ||
| 90 | local | ||
| 91 | String debugstr,res_with_debug,flagstr; | ||
| 92 | case Flags.DEBUG_FLAG(name = flagstr) | ||
| 93 | algorithm | ||
| 94 | ✗ | true := Flags.isSet(inFlag); | |
| 95 | ✗ | debugstr := Print.getString(); | |
| 96 | ✗ | res_with_debug := stringAppendList({res,"\n---DEBUG(",flagstr,")---\n",debugstr,"\n---/DEBUG(",flagstr,")---\n"}); | |
| 97 | then res_with_debug; | ||
| 98 | else res; | ||
| 99 | end matchcontinue; | ||
| 100 | end makeDebugResult; | ||
| 101 | |||
| 102 | protected function parseCommand | ||
| 103 | "Helper function to handleCommand. First tries to parse the given command as a | ||
| 104 | list of statements, and if that fails tries to parse it as a collection of | ||
| 105 | classes. Returns either GlobalScript.Statements or Absyn.Program based on | ||
| 106 | which parser succeeds, or neither if a parser error occured." | ||
| 107 | input String inCommand; | ||
| 108 | output Option<GlobalScript.Statements> outStatements; | ||
| 109 | output Option<Absyn.Program> outProgram; | ||
| 110 | algorithm | ||
| 111 | (outStatements, outProgram) := matchcontinue inCommand | ||
| 112 | local | ||
| 113 | GlobalScript.Statements stmts; | ||
| 114 | Absyn.Program prog; | ||
| 115 | |||
| 116 | case _ | ||
| 117 | algorithm | ||
| 118 | ✗ | ErrorExt.setCheckpoint("parsestring"); | |
| 119 | ✗ | stmts := Parser.parsestringexp(inCommand, "<interactive>"); | |
| 120 | ✗ | ErrorExt.delCheckpoint("parsestring"); | |
| 121 | then | ||
| 122 | (SOME(stmts), NONE()); | ||
| 123 | |||
| 124 | case _ | ||
| 125 | algorithm | ||
| 126 | ✗ | ErrorExt.rollBack("parsestring"); | |
| 127 | ✗ | prog := Parser.parsestring(inCommand, "<interactive>"); | |
| 128 | then | ||
| 129 | (NONE(), SOME(prog)); | ||
| 130 | |||
| 131 | else (NONE(), NONE()); | ||
| 132 | |||
| 133 | end matchcontinue; | ||
| 134 | end parseCommand; | ||
| 135 | |||
| 136 | public function handleCommand | ||
| 137 | "This function handles the commands in form of strings send to the server. | ||
| 138 | If the command is quit, the function returns false, otherwise it sends the | ||
| 139 | string to the parse function and returns true." | ||
| 140 | input String inCommand; | ||
| 141 | output Boolean outContinue; | ||
| 142 | output String outResult; | ||
| 143 | protected | ||
| 144 | Option<GlobalScript.Statements> stmts; | ||
| 145 | Option<Absyn.Program> prog; | ||
| 146 | algorithm | ||
| 147 | ✗ | Print.clearBuf(); | |
| 148 | |||
| 149 | ✗ | if Util.strncmp("quit()", inCommand, 6) then | |
| 150 | outContinue := false; | ||
| 151 | outResult := "Ok\n"; | ||
| 152 | else | ||
| 153 | outContinue := true; | ||
| 154 | |||
| 155 | ✗ | (stmts, prog) := parseCommand(inCommand); | |
| 156 | ✗ | outResult := handleCommand2(stmts, prog, inCommand); | |
| 157 | ✗ | outResult := makeDebugResult(Flags.DUMP, outResult); | |
| 158 | ✗ | outResult := makeDebugResult(Flags.DUMP_GRAPHVIZ, outResult); | |
| 159 | end if; | ||
| 160 | |||
| 161 | ✗ | System.reportProgress(-1, 0) "PHASE_IDLE"; | |
| 162 | end handleCommand; | ||
| 163 | |||
| 164 | protected function handleCommand2 | ||
| 165 | input Option<GlobalScript.Statements> inStatements; | ||
| 166 | input Option<Absyn.Program> inProgram; | ||
| 167 | input String inCommand; | ||
| 168 | output String outResult; | ||
| 169 | algorithm | ||
| 170 | outResult := matchcontinue(inStatements, inProgram) | ||
| 171 | local | ||
| 172 | GlobalScript.Statements stmts; | ||
| 173 | Absyn.Program prog, prog2, ast; | ||
| 174 | String result; | ||
| 175 | list<InteractiveTypes.Variable> vars; | ||
| 176 | SymbolTable table; | ||
| 177 | |||
| 178 | // Interactively evaluate an algorithm statement or expression. | ||
| 179 | case (SOME(stmts), NONE()) | ||
| 180 | algorithm | ||
| 181 | ✗ | result := Interactive.evaluate(stmts, false); | |
| 182 | then result; | ||
| 183 | |||
| 184 | // Add a class or function to the interactive symbol table. | ||
| 185 | case (NONE(), SOME(prog)) | ||
| 186 | algorithm | ||
| 187 | ✗ | table := SymbolTable.get(); | |
| 188 | ✗ | ast := table.ast; | |
| 189 | ✗ | vars := table.vars; | |
| 190 | ✗ | prog2 := Interactive.addScope(prog, vars); | |
| 191 | ✗ | prog2 := ProgramUtil.updateProgram(prog2, ast); | |
| 192 | ✗ | if Flags.isSet(Flags.DUMP) then | |
| 193 | ✗ | Debug.trace("\n--------------- Parsed program ---------------\n"); | |
| 194 | ✗ | Print.printBuf(Dump.unparseStr(prog2)); | |
| 195 | end if; | ||
| 196 | ✗ | if Flags.isSet(Flags.DUMP_GRAPHVIZ) then | |
| 197 | ✗ | DumpGraphviz.dump(prog2); | |
| 198 | end if; | ||
| 199 | ✗ | result := makeClassDefResult(prog) "Return vector of toplevel classnames."; | |
| 200 | ✗ | SymbolTable.setAbsyn(prog2); | |
| 201 | then result; | ||
| 202 | |||
| 203 | // A parser error occured in parseCommand, display the error message. This | ||
| 204 | // is handled here instead of in parseCommand, since parseCommand does not | ||
| 205 | // return a result string. | ||
| 206 | case (NONE(), NONE()) | ||
| 207 | algorithm | ||
| 208 | ✗ | Print.printBuf("Error occurred building AST\n"); | |
| 209 | ✗ | result := Print.getString(); | |
| 210 | ✗ | result := stringAppend(result, "Syntax Error\n"); | |
| 211 | ✗ | result := stringAppend(result, Error.printMessagesStr(false)); | |
| 212 | then result; | ||
| 213 | |||
| 214 | // A non-parser error occured, display the error message. | ||
| 215 | case (_, _) | ||
| 216 | algorithm | ||
| 217 | ✗ | true := isSome(inStatements) or isSome(inProgram); | |
| 218 | ✗ | result := Error.printMessagesStr(false); | |
| 219 | then result; | ||
| 220 | |||
| 221 | else | ||
| 222 | algorithm | ||
| 223 | ✗ | true := isSome(inStatements) or isSome(inProgram); | |
| 224 | ✗ | Error.addMessage(Error.STACK_OVERFLOW, {inCommand}); | |
| 225 | then ""; | ||
| 226 | |||
| 227 | end matchcontinue; | ||
| 228 | end handleCommand2; | ||
| 229 | |||
| 230 | protected function makeClassDefResult | ||
| 231 | "creates a list of classes of the program to be returned from evaluate" | ||
| 232 | input Absyn.Program p; | ||
| 233 | output String res; | ||
| 234 | algorithm | ||
| 235 | res := match p | ||
| 236 | local | ||
| 237 | list<Absyn.Path> names; | ||
| 238 | Absyn.Path scope; | ||
| 239 | list<Absyn.Class> cls; | ||
| 240 | |||
| 241 | case Absyn.PROGRAM(classes=cls,within_=Absyn.WITHIN(scope)) | ||
| 242 | algorithm | ||
| 243 | ✗ | names := list(Absyn.Path.IDENT(AbsynUtil.className(c)) for c in cls); | |
| 244 | ✗ | names := List.map1(names,AbsynUtil.joinPaths,scope); | |
| 245 | ✗ | res := "{" + stringDelimitList(list(AbsynUtil.pathString(n) for n in names),",") + "}\n"; | |
| 246 | then res; | ||
| 247 | |||
| 248 | case Absyn.PROGRAM(classes=cls,within_=Absyn.TOP()) | ||
| 249 | algorithm | ||
| 250 | ✗ | names := list(Absyn.Path.IDENT(AbsynUtil.className(c)) for c in cls); | |
| 251 | ✗ | res := "{" + stringDelimitList(list(AbsynUtil.pathString(n) for n in names),",") + "}\n"; | |
| 252 | then res; | ||
| 253 | |||
| 254 | end match; | ||
| 255 | end makeClassDefResult; | ||
| 256 | |||
| 257 | protected function isModelicaFile | ||
| 258 | "Succeeds if filename ends with .mo or .mof" | ||
| 259 | input String inFilename; | ||
| 260 | output Boolean outIsModelicaFile; | ||
| 261 | protected | ||
| 262 | list<String> lst; | ||
| 263 | String file_ext; | ||
| 264 | algorithm | ||
| 265 | 3960 | lst := System.strtok(inFilename, "."); | |
| 266 | |||
| 267 |
1/2✓ Branch 0 taken 3960 times.
✗ Branch 1 not taken.
|
3960 | if listEmpty(lst) then |
| 268 | outIsModelicaFile := false; | ||
| 269 | else | ||
| 270 | 3960 | file_ext := List.last(lst); | |
| 271 |
5/8✓ Branch 0 taken 2566 times.
✓ Branch 1 taken 1394 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2566 times.
✓ Branch 5 taken 1394 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1394 times.
|
3960 | outIsModelicaFile := file_ext == "mo" or file_ext == "mof"; |
| 272 | end if; | ||
| 273 | end isModelicaFile; | ||
| 274 | |||
| 275 | protected function isEmptyOrFirstIsModelicaFile | ||
| 276 | input list<String> libs; | ||
| 277 | algorithm | ||
| 278 | () := match libs | ||
| 279 | local | ||
| 280 | String f; | ||
| 281 | case {} then (); | ||
| 282 |
2/2✓ Branch 1 taken 1394 times.
✓ Branch 2 taken 1283 times.
|
2677 | case f::_ algorithm true := isModelicaFile(f); then (); |
| 283 | end match; | ||
| 284 | end isEmptyOrFirstIsModelicaFile; | ||
| 285 | |||
| 286 | protected function isFlatModelicaFile | ||
| 287 | "Succeeds if filename ends with .mof" | ||
| 288 | input String filename; | ||
| 289 | protected | ||
| 290 | list<String> lst; | ||
| 291 | String last; | ||
| 292 | algorithm | ||
| 293 | ✗ | lst := System.strtok(filename, "."); | |
| 294 | ✗ | last :: _ := listReverse(lst); | |
| 295 | ✗ | true := stringEq(last, "mof"); | |
| 296 | end isFlatModelicaFile; | ||
| 297 | |||
| 298 | protected function isModelicaScriptFile | ||
| 299 | "Succeeds if filname end with .mos" | ||
| 300 | input String filename; | ||
| 301 | protected | ||
| 302 | list<String> lst; | ||
| 303 | String last; | ||
| 304 | algorithm | ||
| 305 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1706 times.
|
1706 | true := System.regularFileExists(filename); |
| 306 | 1706 | lst := System.strtok(filename, "."); | |
| 307 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1706 times.
|
1706 | last :: _ := listReverse(lst); |
| 308 |
3/4✓ Branch 0 taken 1394 times.
✓ Branch 1 taken 312 times.
✓ Branch 3 taken 1394 times.
✗ Branch 4 not taken.
|
1706 | true := stringEq(last, "mos"); |
| 309 | end isModelicaScriptFile; | ||
| 310 | |||
| 311 | protected function isCodegenTemplateFile | ||
| 312 | "Succeeds if filname end with .tpl" | ||
| 313 | input String filename; | ||
| 314 | protected | ||
| 315 | list<String> lst; | ||
| 316 | String last; | ||
| 317 | algorithm | ||
| 318 | 318 | lst := System.strtok(filename, "."); | |
| 319 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 318 times.
|
318 | last :: _ := listReverse(lst); |
| 320 |
3/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 312 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
|
318 | true := stringEq(last, "tpl"); |
| 321 | end isCodegenTemplateFile; | ||
| 322 | |||
| 323 | protected function showErrors | ||
| 324 | input String errorString; | ||
| 325 | input String errorMessages; | ||
| 326 | algorithm | ||
| 327 |
3/4✓ Branch 0 taken 2666 times.
✓ Branch 1 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2666 times.
|
2684 | if errorString <> "" then |
| 328 | 18 | System.fflush(); | |
| 329 | 18 | System.fputs(errorString, System.StreamType.STDERR); | |
| 330 | 18 | System.fputs("\n", System.StreamType.STDERR); | |
| 331 | 18 | System.fflush(); | |
| 332 | end if; | ||
| 333 | |||
| 334 |
3/4✓ Branch 0 taken 2330 times.
✓ Branch 1 taken 354 times.
✓ Branch 3 taken 2330 times.
✗ Branch 4 not taken.
|
2684 | if errorMessages <> "" then |
| 335 | 354 | System.fflush(); | |
| 336 | 354 | System.fputs(errorMessages, System.StreamType.STDERR); | |
| 337 | 354 | System.fputs("\n", System.StreamType.STDERR); | |
| 338 | 354 | System.fflush(); | |
| 339 | end if; | ||
| 340 | end showErrors; | ||
| 341 | |||
| 342 | protected function loadLib | ||
| 343 | input String inLib; | ||
| 344 | protected | ||
| 345 | Boolean is_modelica_file; | ||
| 346 | algorithm | ||
| 347 | 1283 | is_modelica_file := isModelicaFile(inLib); | |
| 348 | () := matchcontinue is_modelica_file | ||
| 349 | local | ||
| 350 | String mp; | ||
| 351 | Absyn.Program pnew, p; | ||
| 352 | Absyn.Path path; | ||
| 353 | |||
| 354 | // A .mo-file. | ||
| 355 | case true | ||
| 356 | algorithm | ||
| 357 | 1283 | p := SymbolTable.getAbsyn(); | |
| 358 | 1283 | pnew := CevalScript.loadFile(inLib, "UTF-8", p, true, true, false); | |
| 359 | 1265 | SymbolTable.setAbsyn(pnew); | |
| 360 | then (); | ||
| 361 | |||
| 362 | // some libs present | ||
| 363 | case false | ||
| 364 | algorithm | ||
| 365 | ✗ | path := AbsynUtil.stringPath(inLib); | |
| 366 | ✗ | mp := Settings.getModelicaPath(Testsuite.isRunning()); | |
| 367 | ✗ | p := SymbolTable.getAbsyn(); | |
| 368 | ✗ | (pnew, true) := CevalScript.loadModel({(path, "command-line argument", {"default"}, false)}, mp, p, true, true, true, false); | |
| 369 | ✗ | SymbolTable.setAbsyn(pnew); | |
| 370 | then (); | ||
| 371 | |||
| 372 | // problem with the libs, ignore! | ||
| 373 | case false | ||
| 374 | algorithm | ||
| 375 | ✗ | Print.printErrorBuf("Failed to load library: " + inLib + "!\n"); | |
| 376 | ✗ | then | |
| 377 | fail(); | ||
| 378 | |||
| 379 | case true | ||
| 380 | algorithm | ||
| 381 | 18 | Print.printErrorBuf("Failed to parse file: " + inLib + "!\n"); | |
| 382 | 18 | then | |
| 383 | fail(); | ||
| 384 | |||
| 385 | end matchcontinue; | ||
| 386 | end loadLib; | ||
| 387 | |||
| 388 | protected function translateFile | ||
| 389 | "This function invokes the translator on a source file. The argument should be | ||
| 390 | a list with a single file name, with the rest of the list being an optional | ||
| 391 | list of libraries and .mo-files if the file is a .mo-file" | ||
| 392 | input list<String> inStringLst; | ||
| 393 | protected | ||
| 394 | String f; | ||
| 395 | list<String> libs; | ||
| 396 | Absyn.Path cname; | ||
| 397 | Boolean runBackend, runSilent; | ||
| 398 | GlobalScript.Statements stmts; | ||
| 399 | String cls, fileNamePrefix, fmuVersion, fmuType, fmuPlatformsStr; | ||
| 400 | Integer fmuVersionInt; | ||
| 401 | list<String> fmuPlatforms, fmuTypeList; | ||
| 402 | algorithm | ||
| 403 | // Execute the given script if --cmd is used. | ||
| 404 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2676 times.
|
2677 | if not stringEmpty(Flags.getConfigString(Flags.EXECUTE_COMMAND)) then |
| 405 | 1 | stmts := Parser.parsestringexp(Flags.getConfigString(Flags.EXECUTE_COMMAND)); | |
| 406 | 1 | showErrors(Print.getErrorString(), ErrorExt.printMessagesStr(false)); | |
| 407 | 1 | Interactive.evaluateToStdOut(stmts, true); | |
| 408 | |||
| 409 | // Return if there's nothing more to do to avoid showing the help message. | ||
| 410 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
1 | if listEmpty(inStringLst) and stringEmpty(Config.classToInstantiate()) then |
| 411 | ✗ | return; | |
| 412 | end if; | ||
| 413 | end if; | ||
| 414 | |||
| 415 | () := matchcontinue inStringLst | ||
| 416 | // A .mo-file, followed by an optional list of extra .mo-files and libraries. | ||
| 417 | // The last class in the first file will be instantiated. | ||
| 418 | case libs | ||
| 419 | algorithm | ||
| 420 | //print("Class to instantiate: " + Config.classToInstantiate() + "\n"); | ||
| 421 | 2677 | isEmptyOrFirstIsModelicaFile(libs); | |
| 422 | 1283 | execStatReset(); | |
| 423 | // Parse libraries and extra mo-files that might have been given at the command line. | ||
| 424 |
2/2✓ Branch 0 taken 1283 times.
✓ Branch 1 taken 1265 times.
|
2548 | for lib in libs loop |
| 425 | 1283 | loadLib(lib); | |
| 426 | end for; | ||
| 427 | |||
| 428 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1265 times.
|
1265 | if Flags.isSet(Flags.DUMP) then |
| 429 | ✗ | Debug.trace("\n--------------- Parsed program ---------------\n"); | |
| 430 | ✗ | Dump.unparseStr(SymbolTable.getAbsyn()); | |
| 431 | ✗ | print(Print.getString()); | |
| 432 | end if; | ||
| 433 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1265 times.
|
1265 | if Flags.isSet(Flags.DUMP_JL) then |
| 434 | ✗ | Debug.trace("\n--------------- Julia representation of the parsed program ---------------\n"); | |
| 435 | ✗ | print(Tpl.tplString(AbsynJLDumpTpl.dump, SymbolTable.getAbsyn()) + "\n"); | |
| 436 | end if; | ||
| 437 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1265 times.
|
1265 | if Flags.isSet(Flags.DUMP_GRAPHVIZ) then |
| 438 | ✗ | DumpGraphviz.dump(SymbolTable.getAbsyn()); | |
| 439 | end if; | ||
| 440 | |||
| 441 | 1265 | execStat("Parsed file"); | |
| 442 | |||
| 443 | 1265 | cls := Config.classToInstantiate(); | |
| 444 | // If no class was explicitly specified, instantiate the last class in the | ||
| 445 | // program. Otherwise, instantiate the given class name. | ||
| 446 |
2/2✓ Branch 0 taken 1260 times.
✓ Branch 1 taken 5 times.
|
1265 | cname := if stringEmpty(cls) then AbsynUtil.lastClassname(SymbolTable.getAbsyn()) else AbsynUtil.stringPath(cls); |
| 447 | 1264 | fileNamePrefix := Util.stringReplaceChar(AbsynUtil.pathString(cname), ".", "_"); | |
| 448 | |||
| 449 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1262 times.
|
1264 | if Flags.getConfigBool(Flags.EXPORT_FMU) then |
| 450 | 2 | fmuVersionInt := Flags.getConfigEnum(Flags.FMU_VERSION); | |
| 451 | fmuVersion := match fmuVersionInt | ||
| 452 | case 10 then "1.0"; | ||
| 453 | case 20 then "2.0"; | ||
| 454 | case 30 then "3.0"; | ||
| 455 | end match; | ||
| 456 | 2 | FlagsUtil.setConfigString(Flags.FMI_VERSION, fmuVersion); | |
| 457 | 2 | fmuTypeList := Flags.getConfigStringList(Flags.FMU_TYPE); | |
| 458 | 2 | fmuType := stringDelimitList(fmuTypeList, "_"); | |
| 459 | 2 | fmuPlatformsStr := Flags.getConfigString(Flags.FMU_PLATFORMS); | |
| 460 | 2 | fmuPlatforms := Util.stringSplitAtChar(fmuPlatformsStr, ","); | |
| 461 | 2 | CevalScriptBackend.callBuildModelFMU(FCore.emptyCache(), FGraph.empty(), cname, | |
| 462 | fmuVersion, fmuType, fileNamePrefix, true, fmuPlatforms, NONE()); | ||
| 463 | 2 | showErrors(Print.getErrorString(), ErrorExt.printMessagesStr(false)); | |
| 464 | 2 | System.fflush(); | |
| 465 | else | ||
| 466 |
2/4✓ Branch 1 taken 1262 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1262 times.
|
1262 | runBackend := Config.simulationCg() or Config.simulation(); |
| 467 | 1262 | runSilent := Config.silent(); | |
| 468 | |||
| 469 | 1262 | CevalScriptBackend.translateModel(FCore.emptyCache(), FGraph.empty(), cname, | |
| 470 | fileNamePrefix, runBackend, runSilent, NONE()); | ||
| 471 | 969 | showErrors(Print.getErrorString(), ErrorExt.printMessagesStr(false)); | |
| 472 | end if; | ||
| 473 | then (); | ||
| 474 | |||
| 475 | /* Modelica script file .mos */ | ||
| 476 | case f::libs | ||
| 477 | algorithm | ||
| 478 | 1706 | isModelicaScriptFile(f); | |
| 479 | // loading possible libraries given at the command line | ||
| 480 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1394 times.
|
1394 | for lib in libs loop |
| 481 | ✗ | loadLib(lib); | |
| 482 | end for; | ||
| 483 | |||
| 484 | //System.startTimer(); | ||
| 485 | //print("\nParseExp"); | ||
| 486 | // parse our algorithm given in the script | ||
| 487 | 1394 | stmts := Parser.parseexp(f); | |
| 488 | //System.stopTimer(); | ||
| 489 | //print("\nParseExp: " + realString(System.getTimerIntervalTime())); | ||
| 490 | |||
| 491 | // are there any errors? | ||
| 492 | // show errors if there are any | ||
| 493 | 1394 | showErrors(Print.getErrorString(), ErrorExt.printMessagesStr(false)); | |
| 494 | // evaluate statements and print the result to stdout directly | ||
| 495 | 1394 | Interactive.evaluateToStdOut(stmts, true); | |
| 496 | then | ||
| 497 | (); | ||
| 498 | |||
| 499 | case {f} /* A template file .tpl (in the Susan language)*/ | ||
| 500 | algorithm | ||
| 501 | 318 | isCodegenTemplateFile(f); | |
| 502 | ✗ | TplMain.main(f, Flags.getConfigString(Flags.TPL_OUTPUT_DIR)); | |
| 503 | then | ||
| 504 | (); | ||
| 505 | |||
| 506 | // deal with problems | ||
| 507 | case f::_ | ||
| 508 | algorithm | ||
| 509 |
1/2✓ Branch 1 taken 318 times.
✗ Branch 2 not taken.
|
318 | if System.regularFileExists(f) then |
| 510 | 318 | print("Error processing file: "); | |
| 511 | else | ||
| 512 | ✗ | print("File does not exist: "); | |
| 513 | end if; | ||
| 514 | |||
| 515 | 318 | print(f); print("\n"); System.fflush(); | |
| 516 | // show errors if there are any | ||
| 517 | 318 | showErrors(Print.getErrorString(), ErrorExt.printMessagesStr(false)); | |
| 518 | 318 | then | |
| 519 | fail(); | ||
| 520 | |||
| 521 | end matchcontinue; | ||
| 522 | end translateFile; | ||
| 523 | |||
| 524 | protected function interactivemode | ||
| 525 | "Initiate the interactive mode using socket communication." | ||
| 526 | protected | ||
| 527 | Integer shandle; | ||
| 528 | Boolean b; | ||
| 529 | String str,replystr; | ||
| 530 | algorithm | ||
| 531 | ✗ | shandle := Socket.waitforconnect(29500); | |
| 532 | ✗ | if shandle == -1 then | |
| 533 | ✗ | fail(); | |
| 534 | end if; | ||
| 535 | while true loop | ||
| 536 | ✗ | str := Socket.handlerequest(shandle); | |
| 537 | ✗ | if Flags.isSet(Flags.INTERACTIVE_DUMP) then | |
| 538 | ✗ | Debug.trace("------- Recieved Data from client -----\n"); | |
| 539 | ✗ | Debug.trace(str); | |
| 540 | ✗ | Debug.trace("------- End recieved Data-----\n"); | |
| 541 | end if; | ||
| 542 | ✗ | (b,replystr) := handleCommand(str) "Print.clearErrorBuf &" ; | |
| 543 | ✗ | replystr := if b then replystr else "quit requested, shutting server down\n"; | |
| 544 | ✗ | Socket.sendreply(shandle, replystr); | |
| 545 | ✗ | if not b then | |
| 546 | ✗ | Socket.close(shandle); | |
| 547 | ✗ | Socket.cleanup(); | |
| 548 | break; | ||
| 549 | end if; | ||
| 550 | end while; | ||
| 551 | end interactivemode; | ||
| 552 | |||
| 553 | protected function interactivemodeZMQ | ||
| 554 | "Initiate the interactive mode using ZMQ communication." | ||
| 555 | protected | ||
| 556 | Option<Integer> zmqSocket; | ||
| 557 | Boolean b; | ||
| 558 | String str,replystr,suffix; | ||
| 559 | algorithm | ||
| 560 | ✗ | suffix := Flags.getConfigString(Flags.ZEROMQ_FILE_SUFFIX); | |
| 561 | ✗ | zmqSocket := ZeroMQ.initialize(if suffix=="" then "" else ("."+suffix), Flags.isSet(Flags.ZMQ_LISTEN_TO_ALL), Flags.getConfigInt(Flags.INTERACTIVE_PORT)); | |
| 562 | ✗ | false := valueEq(SOME(0), zmqSocket); | |
| 563 | while true loop | ||
| 564 | ✗ | str := ZeroMQ.handleRequest(zmqSocket); | |
| 565 | ✗ | if Flags.isSet(Flags.INTERACTIVE_DUMP) then | |
| 566 | ✗ | Debug.trace("------- Recieved Data from client -----\n"); | |
| 567 | ✗ | Debug.trace(str); | |
| 568 | ✗ | Debug.trace("------- End recieved Data-----\n"); | |
| 569 | end if; | ||
| 570 | ✗ | (b,replystr) := handleCommand(str); | |
| 571 | ✗ | replystr := if b then replystr else "quit requested, shutting server down\n"; | |
| 572 | ✗ | ZeroMQ.sendReply(zmqSocket, replystr); | |
| 573 | ✗ | if not b then | |
| 574 | ✗ | ZeroMQ.close(zmqSocket); | |
| 575 | break; | ||
| 576 | end if; | ||
| 577 | end while; | ||
| 578 | end interactivemodeZMQ; | ||
| 579 | |||
| 580 | public function readSettings | ||
| 581 | " author: x02lucpo | ||
| 582 | Checks if 'settings.mos' exist and uses handleCommand with runScript(...) to execute it. | ||
| 583 | Checks if '-s <file>.mos' has been" | ||
| 584 | input list<String> inArguments; | ||
| 585 | protected | ||
| 586 | String settings_file; | ||
| 587 | algorithm | ||
| 588 | 2677 | settings_file := Util.flagValue("-s", inArguments); | |
| 589 | |||
| 590 |
2/4✓ Branch 0 taken 2677 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2677 times.
✗ Branch 4 not taken.
|
2677 | if settings_file <> "" then |
| 591 | ✗ | settings_file := System.trim(settings_file, " \""); | |
| 592 | ✗ | readSettingsFile(settings_file); | |
| 593 | end if; | ||
| 594 | end readSettings; | ||
| 595 | |||
| 596 | protected function readSettingsFile | ||
| 597 | input String filePath; | ||
| 598 | protected | ||
| 599 | String command; | ||
| 600 | algorithm | ||
| 601 | ✗ | if System.regularFileExists(filePath) then | |
| 602 | ✗ | command := "runScript(\"" + filePath + "\")"; | |
| 603 | ✗ | handleCommand(command); | |
| 604 | end if; | ||
| 605 | end readSettingsFile; | ||
| 606 | |||
| 607 | public function setWindowsPaths | ||
| 608 | "@author: adrpo | ||
| 609 | Set the windows paths for MSYS. | ||
| 610 | Do some checks on where needed things are present. | ||
| 611 | BIG WARNING: if MinGW gcc version from OMDev or OpenModelica/MinGW | ||
| 612 | changes you will need to change here!" | ||
| 613 | input String inOMHome; | ||
| 614 | algorithm | ||
| 615 | () := match inOMHome | ||
| 616 | local | ||
| 617 | String oldPath, newPath, omHome, omdevPath, msysPath, mingwDir, binDir, libBinDir, msysBinDir, omLibDir; | ||
| 618 | Boolean hasBinDir, hasLibBinDir, isMSVC; | ||
| 619 | |||
| 620 | // check if we have OMDEV set | ||
| 621 | case omHome | ||
| 622 | algorithm | ||
| 623 | ✗ | System.setEnv("OPENMODELICAHOME",omHome,true); | |
| 624 | ✗ | omdevPath := Util.makeValueOrDefault(System.readEnv,"OMDEV",""); | |
| 625 | // if we don't have something in OMDEV use OMHOME | ||
| 626 | ✗ | if stringEq(omdevPath, "") then | |
| 627 | omdevPath := omHome; | ||
| 628 | end if; | ||
| 629 | ✗ | msysPath := omdevPath + "\\tools\\msys"; | |
| 630 | ✗ | mingwDir := System.openModelicaPlatform(); | |
| 631 | ✗ | msysBinDir := msysPath + "\\usr\\bin"; | |
| 632 | ✗ | binDir := msysPath + "\\" + mingwDir + "\\bin"; | |
| 633 | // An MSVC build ships no MSYS toolchain at all - Compile.bat locates | ||
| 634 | // Visual Studio itself - so there is nothing to search for or report. | ||
| 635 | ✗ | isMSVC := 0 == System.stringFind(mingwDir, "msvc"); | |
| 636 | ✗ | if isMSVC then | |
| 637 | libBinDir := binDir; | ||
| 638 | elseif System.getCCompiler() == "gcc" then | ||
| 639 | ✗ | libBinDir := msysPath + "\\" + mingwDir + "\\lib\\gcc\\" + System.gccDumpMachine() + "\\" + System.gccVersion(); | |
| 640 | else // if is clang | ||
| 641 | libBinDir := binDir; | ||
| 642 | end if; | ||
| 643 | // do we have bin and lib bin? | ||
| 644 | ✗ | hasBinDir := System.directoryExists(binDir); | |
| 645 | ✗ | hasLibBinDir := System.directoryExists(libBinDir); | |
| 646 | ✗ | omLibDir := omHome + "\\lib\\" + Autoconf.triple + "\\omc"; | |
| 647 | ✗ | if isMSVC then | |
| 648 | ✗ | oldPath := System.readEnv("PATH"); | |
| 649 | ✗ | newPath := stringAppendList({omHome, "\\bin;", omLibDir, ";"}); | |
| 650 | ✗ | newPath := System.stringReplace(newPath, "/", "\\") + oldPath; | |
| 651 | ✗ | System.setEnv("PATH",newPath,true); | |
| 652 | elseif hasBinDir and hasLibBinDir | ||
| 653 | then | ||
| 654 | ✗ | oldPath := System.readEnv("PATH"); | |
| 655 | ✗ | newPath := stringAppendList({omHome, "\\bin;", omLibDir, ";", binDir + ";", libBinDir + ";", msysBinDir + ";"}); | |
| 656 | ✗ | newPath := System.stringReplace(newPath, "/", "\\") + oldPath; | |
| 657 | // print("Path set: " + newPath + "\n"); | ||
| 658 | ✗ | System.setEnv("PATH",newPath,true); | |
| 659 | else | ||
| 660 | // do not display anything if -d=disableWindowsPathCheckWarning | ||
| 661 | ✗ | if not Flags.isSet(Flags.DISABLE_WINDOWS_PATH_CHECK_WARNING) then | |
| 662 | ✗ | print("We could not find some needed MINGW paths in $OPENMODELICAHOME or $OMDEV. Searched for paths:\n"); | |
| 663 | ✗ | print("\t" + binDir + (if hasBinDir then " [found] " else " [not found] ") + "\n"); | |
| 664 | ✗ | print("\t" + libBinDir + (if hasLibBinDir then " [found] " else " [not found] ") + "\n"); | |
| 665 | end if; | ||
| 666 | end if; | ||
| 667 | then (); | ||
| 668 | end match; | ||
| 669 | end setWindowsPaths; | ||
| 670 | |||
| 671 | protected function setDefaultCC "Reads the environment variable CC to change the default CC" | ||
| 672 | algorithm | ||
| 673 | try | ||
| 674 | 2677 | System.setCCompiler(System.readEnv("CC")); | |
| 675 | else | ||
| 676 | end try; | ||
| 677 | end setDefaultCC; | ||
| 678 | |||
| 679 | public function init | ||
| 680 | "Does some things and also reads all flags from the command line arguments." | ||
| 681 | input list<String> args "command line arguments"; | ||
| 682 | output list<String> args_1 "arguments that are not flags"; | ||
| 683 | algorithm | ||
| 684 | // set glib G_SLICE to always-malloc as is rummored to be better for Boehm GC | ||
| 685 | 2677 | System.setEnv("G_SLICE", "always-malloc", true); | |
| 686 | // call GC_init() the first thing we do! | ||
| 687 | 2677 | System.initGarbageCollector(); | |
| 688 | // Experimentally found to make the testsuite pass on asap.openmodelica.org. | ||
| 689 | // 150M for Windows, 300M for others makes the GC try to unmap less and so it crashes less. | ||
| 690 | // Disabling unmap is another alternative that seems to work well (but could cause the memory consumption to not be released, and requires manually calling collect and unmap | ||
| 691 | if true then | ||
| 692 | 2677 | GCExt.setForceUnmapOnGcollect(Autoconf.os == "Windows_NT"); | |
| 693 | else | ||
| 694 | GCExt.expandHeap(if Autoconf.os == "Windows_NT" | ||
| 695 | then 1024*1024*150 | ||
| 696 | else 1024*1024*300); | ||
| 697 | end if; | ||
| 698 | 2677 | Global.initialize(); | |
| 699 | 2677 | ErrorExt.registerModelicaFormatError(); | |
| 700 | 2677 | ErrorExt.initAssertionFunctions(); | |
| 701 | 2677 | System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL); | |
| 702 | 2677 | args_1 := FlagsUtil.new(args); | |
| 703 | 2677 | FlagsUtil.applyNumProcEnvironment(); | |
| 704 | 2677 | setDefaultCC(); | |
| 705 | 2677 | SymbolTable.reset(); | |
| 706 | 2677 | BackendInterfaceImplementation.initializeBackendInterface(); | |
| 707 | end init; | ||
| 708 | |||
| 709 | public function main | ||
| 710 | "This is the main function that the MetaModelica Compiler (MMC) runtime system | ||
| 711 | calls to start the translation." | ||
| 712 | input list<String> args; | ||
| 713 | protected | ||
| 714 | list<String> args_1; | ||
| 715 | Integer seconds; | ||
| 716 | algorithm | ||
| 717 | 2677 | execStatReset(); | |
| 718 | try | ||
| 719 | try | ||
| 720 | 2677 | args_1 := init(args); | |
| 721 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2677 times.
|
2677 | if Flags.isSet(Flags.GC_PROF) then |
| 722 | ✗ | print(GCExt.profStatsStr(GCExt.getProfStats(), head="GC stats after initialization:") + "\n"); | |
| 723 | end if; | ||
| 724 | 2677 | seconds := Flags.getConfigInt(Flags.ALARM); | |
| 725 |
2/2✓ Branch 0 taken 2675 times.
✓ Branch 1 taken 2 times.
|
2677 | if seconds > 0 then |
| 726 | 2675 | System.alarm(seconds); | |
| 727 | end if; | ||
| 728 | 2677 | main2(args_1); | |
| 729 | else | ||
| 730 | 318 | ErrorExt.clearMessages(); | |
| 731 |
1/2✓ Branch 0 taken 318 times.
✗ Branch 1 not taken.
|
318 | failure(FlagsUtil.new(args)); |
| 732 | ✗ | print(ErrorExt.printMessagesStr(false)); print("\n"); | |
| 733 | ✗ | fail(); | |
| 734 | end try; | ||
| 735 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2359 times.
|
2359 | if Flags.isSet(Flags.GC_PROF) then |
| 736 | ✗ | print(GCExt.profStatsStr(GCExt.getProfStats(), head="GC stats at end of program:") + "\n"); | |
| 737 | end if; | ||
| 738 | else | ||
| 739 | ✗ | print(StackOverflow.errorPrefix() + " detected and was not caught.\n" + | |
| 740 | "Send us a bug report at https://trac.openmodelica.org/OpenModelica/newticket\n" + | ||
| 741 | " Include the following trace:\n"); | ||
| 742 | ✗ | for s in StackOverflow.readableStacktraceMessages() loop | |
| 743 | ✗ | print(s); | |
| 744 | ✗ | print("\n"); | |
| 745 | end for; | ||
| 746 | end try annotation(__OpenModelica_stackOverflowCheckpoint=true); | ||
| 747 | end main; | ||
| 748 | |||
| 749 | protected function main2 | ||
| 750 | "This is not the main function that the MetaModelica Compiler (MMC) runtime | ||
| 751 | system calls to start the translation." | ||
| 752 | input list<String> args; | ||
| 753 | protected | ||
| 754 | String interactiveMode; | ||
| 755 | algorithm | ||
| 756 | // Version requested using --version. | ||
| 757 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2677 times.
|
2677 | if Config.versionRequest() then |
| 758 | ✗ | print(Settings.getVersionNr() + "\n"); | |
| 759 | ✗ | return; | |
| 760 | end if; | ||
| 761 | |||
| 762 | // Don't allow running omc as root due to security risks. | ||
| 763 | 2677 | interactiveMode := Flags.getConfigString(Flags.INTERACTIVE); | |
| 764 |
1/10✗ Branch 1 not taken.
✓ Branch 2 taken 2677 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
2677 | if System.userIsRoot() and (interactiveMode == "tcp" or interactiveMode == "zmq") then |
| 765 | ✗ | Error.addMessage(Error.ROOT_USER_INTERACTIVE, {}); | |
| 766 | ✗ | print(ErrorExt.printMessagesStr(false)); | |
| 767 | ✗ | fail(); | |
| 768 | end if; | ||
| 769 | |||
| 770 | // Setup mingw path only once | ||
| 771 | // adrpo: NEVER MOVE THIS CASE FROM HERE OR PUT ANY OTHER CASES BEFORE IT | ||
| 772 | // without asking Adrian.Pop@liu.se | ||
| 773 | if Autoconf.os == "Windows_NT" then | ||
| 774 | setWindowsPaths(Settings.getInstallationDirectoryPath()); | ||
| 775 | end if; | ||
| 776 | |||
| 777 | try | ||
| 778 | 2677 | Settings.getInstallationDirectoryPath(); | |
| 779 | |||
| 780 | 2677 | readSettings(args); | |
| 781 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2677 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
2677 | if interactiveMode == "tcp" then |
| 782 | ✗ | interactivemode(); | |
| 783 | elseif interactiveMode == "zmq" then | ||
| 784 | ✗ | interactivemodeZMQ(); | |
| 785 | else // No interactive flag given, try to flatten the file. | ||
| 786 | 2677 | translateFile(args); | |
| 787 | end if; | ||
| 788 | else // Something went wrong, print an appropriate error. | ||
| 789 | // OMC called with no arguments, print usage information and quit. | ||
| 790 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 318 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
318 | if listEmpty(args) and Config.classToInstantiate()=="" then |
| 791 | ✗ | if not Config.helpRequest() then | |
| 792 | ✗ | print(FlagsUtil.printUsage()); System.fflush(); | |
| 793 | end if; | ||
| 794 | ✗ | return; | |
| 795 | end if; | ||
| 796 | |||
| 797 | try | ||
| 798 | 318 | Settings.getInstallationDirectoryPath(); | |
| 799 | 318 | print("# Error encountered! Exiting...\n"); System.fflush(); | |
| 800 | 318 | print("# Please check the error message and the flags.\n"); System.fflush(); | |
| 801 | 318 | Print.printBuf("\n\n----\n\nError buffer:\n\n"); System.fflush(); | |
| 802 | 318 | print(Print.getErrorString()); System.fflush(); | |
| 803 | 318 | print(ErrorExt.printMessagesStr(false)); System.fflush(); print("\n"); System.fflush(); | |
| 804 | else | ||
| 805 | ✗ | print("Error: Failed to retrieve the installation directory path!\n"); System.fflush(); | |
| 806 | end try; | ||
| 807 | 318 | fail(); | |
| 808 | end try; | ||
| 809 | end main2; | ||
| 810 | |||
| 811 | annotation(__OpenModelica_Interface="backend_main"); | ||
| 812 | end Main; | ||
| 813 |