Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 40.0% 761 / 0 / 1902
Functions: -% 0 / 1 / 1
Branches: 36.7% 331 / 0 / 902

OMCompiler/Compiler/Script/Interactive.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 Interactive
37 " file: Interactive.mo
38 package: Interactive
39 description: This module contain functionality for model management,
40 expression evaluation, etc. in the interactive environment.
41
42 $Id: Interactive.mo 25580 2015-04-16 14:04:16Z jansilar $
43
44 This module contain functionality for model management, expression evaluation, etc.
45 in the interactive environment.
46 The module defines a symboltable used in the interactive environment containing:
47 - Modelica models (described using Absyn AST)
48 - InteractiveTypes.Variable bindings
49 - Compiled functions (so they do not need to be recompiled)
50 - Instantiated classes (that can be reused, not impl. yet)
51 - Modelica models in SCode form (to speed up instantiation. not impl. yet)"
52
53 //public imports
54 import Absyn;
55 import ProgramUtil;
56 import AbsynUtil;
57 import Builtin;
58 import ConnectionGraph;
59 import DAE;
60 import FCore;
61 import Global;
62 import SCode;
63 import AbsynToSCode;
64 import Settings;
65 import GlobalScript;
66 import Values;
67
68
69 // protected imports
70 protected
71
72 import Ceval;
73 import CevalScript;
74 import ClassInf;
75 import ClockIndexes;
76 import Config;
77 import DAE.Connect;
78 import DAEDump;
79 import DAEUtil;
80 import Dump;
81 import Error;
82 import ErrorExt;
83 import ExpressionBasics;
84 import ExpressionSimplify;
85 import FGraph;
86 import Flags;
87 import GCExt;
88 import GlobalScriptDump;
89 import InnerOuter;
90 import Inst;
91 import InstHashTable;
92 import InstTypes;
93 import InstUtil;
94 import InteractiveUtil;
95 import List;
96 import Lookup;
97 import MetaUtil;
98 import Mod;
99 import NFApi;
100 import Parser;
101 import Print;
102 import Refactor;
103 import SCodeUtil;
104 import StackOverflow;
105 import Static;
106 import StaticScript;
107 import StringUtil;
108 import SymbolTable;
109 import System;
110 import Testsuite;
111 import Types;
112 import UnitAbsyn;
113 import Util;
114 import ValuesDump;
115 import ValuesUtil;
116
117 import MetaModelica.Dangerous;
118 import ClassInfUtil;
119
120 public uniontype AnnotationType
121 record ICON_ANNOTATION end ICON_ANNOTATION;
122 record DIAGRAM_ANNOTATION end DIAGRAM_ANNOTATION;
123 end AnnotationType;
124
125 public uniontype GraphicEnvCache
126 "Used by buildEnvForGraphicProgram to avoid excessive work."
127 record GRAPHIC_ENV_NO_CACHE
128 Absyn.Program program;
129 Absyn.Path modelPath;
130 end GRAPHIC_ENV_NO_CACHE;
131
132 record GRAPHIC_ENV_PARTIAL_CACHE
133 Absyn.Program program;
134 Absyn.Path modelPath;
135 FCore.Cache cache;
136 FCore.Graph env;
137 end GRAPHIC_ENV_PARTIAL_CACHE;
138
139 record GRAPHIC_ENV_FULL_CACHE
140 Absyn.Program program;
141 Absyn.Path modelPath;
142 FCore.Cache cache;
143 FCore.Graph env;
144 end GRAPHIC_ENV_FULL_CACHE;
145 end GraphicEnvCache;
146
147 type Access = enumeration(hide, icon, documentation, diagram, nonPackageText, nonPackageDuplicate, packageText, packageDuplicate, all);
148
149 public function evaluate
150 "This function evaluates expressions or statements feed interactively to the compiler.
151 inputs: (GlobalScript.Statements, bool /* verbose */)
152 outputs: string:
153 The resulting string after evaluation. If an error has occurred, this string
154 will be empty. The error messages can be retrieved by calling print_messages_str()
155 in Error.mo."
156 input GlobalScript.Statements inStatements;
157 input Boolean verbose;
158 output String outString;
159 protected
160 Boolean semicolon;
161 String res;
162 list<String> resl = {};
163 algorithm
164
2/2
✓ Branch 0 taken 5588 times.
✓ Branch 1 taken 289 times.
5877 for stmt in inStatements.interactiveStmtLst loop
165 5588 semicolon := inStatements.semicolon;
166 5588 showStatement(stmt, semicolon, true);
167 5588 res := evaluate2(stmt);
168
169
3/4
✓ Branch 1 taken 301 times.
✓ Branch 2 taken 5287 times.
✓ Branch 3 taken 301 times.
✗ Branch 4 not taken.
5588 if getEcho() and (verbose or not semicolon) then
170 301 res := stringAppend(res, "\n");
171 resl := res :: resl;
172 end if;
173
174 5588 showStatement(stmt, semicolon, false);
175 end for;
176
177 289 outString := stringAppendList(Dangerous.listReverseInPlace(resl));
178 end evaluate;
179
180 public function evaluateToStdOut
181 "This function evaluates expressions or statements feed interactively to the compiler.
182 The resulting string after evaluation is printed.
183 If an error has occurred, this string will be empty.
184 The error messages can be retrieved by calling print_messages_str() in Error.mo."
185 input GlobalScript.Statements statements;
186 input Boolean verbose;
187 protected
188 Boolean semicolon;
189 String res;
190 algorithm
191 1395 semicolon := statements.semicolon;
192
193
2/2
✓ Branch 0 taken 13289 times.
✓ Branch 1 taken 1389 times.
14678 for stmt in statements.interactiveStmtLst loop
194 13289 showStatement(stmt, semicolon, true);
195 13289 res := evaluate2(stmt);
196
197
3/4
✓ Branch 1 taken 12743 times.
✓ Branch 2 taken 540 times.
✓ Branch 3 taken 12743 times.
✗ Branch 4 not taken.
13283 if getEcho() and (verbose or not semicolon) then
198 12743 print(res);
199 12743 print("\n");
200 end if;
201
202 13283 showStatement(stmt, semicolon, false);
203 end for;
204 end evaluateToStdOut;
205
206 public function evaluateFork
207 "As evaluateToStdOut, but takes the inputs as a tuple of mos-script file and symbol table.
208 As it is supposed to work in a thread without output, it also flushes the error-buffer since that will otherwise be lost to the void."
209 input tuple<String,SymbolTable> inTpl;
210 output Boolean b;
211 algorithm
212 b := matchcontinue inTpl
213 local
214 String mosfile;
215 GlobalScript.Statements statements;
216 SymbolTable st;
217 Absyn.Program ast;
218 Option<SCode.Program> explodedAst;
219
220 case (mosfile,st)
221 algorithm
222 ✗ SymbolTable.reset();
223 ✗ SymbolTable.setAbsyn(st.ast);
224 ✗ SymbolTable.setSCode(st.explodedAst);
225 ✗ setGlobalRoot(Global.instOnlyForcedFunctions, NONE()); // thread-local root that has to be set!
226 ✗ statements := Parser.parseexp(mosfile);
227 ✗ evaluateToStdOut(statements,true);
228 ✗ print(Error.printMessagesStr(false));
229 then true;
230 else
231 algorithm
232 ✗ print(Error.printMessagesStr(false));
233 then false;
234 end matchcontinue;
235 end evaluateFork;
236
237 protected function showStatement
238 input GlobalScript.Statement s;
239 input Boolean semicolon;
240 input Boolean start;
241 protected
242 Boolean testsuite;
243 algorithm
244
2/2
✓ Branch 1 taken 36974 times.
✓ Branch 2 taken 774 times.
37748 if not Flags.isSet(Flags.SHOW_STATEMENT) then
245 36974 return;
246 end if;
247
248 774 testsuite := Testsuite.isRunning();
249
250 () := matchcontinue(start, testsuite)
251
252 // running testsuite
253 case (true, true)
254 algorithm
255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 383 times.
383 print("Evaluating: " + printIstmtStr(GlobalScript.ISTMTS({s}, semicolon)) + "\n");
256 383 System.fflush();
257 then
258 ();
259
260 case (false, true) then ();
261
262 // not running testsuite, show more!
263 case (true, false)
264 algorithm
265 ✗ System.realtimeTick(ClockIndexes.RT_CLOCK_SHOW_STATEMENT);
266 ✗ print("Evaluating: > " + printIstmtStr(GlobalScript.ISTMTS({s}, semicolon)) + "\n");
267 ✗ System.fflush();
268 then
269 ();
270
271 case (false, false)
272 algorithm
273 ✗ print("Evaluated: < " + realString(System.realtimeTock(ClockIndexes.RT_CLOCK_SHOW_STATEMENT)) + " / " + printIstmtStr(GlobalScript.ISTMTS({s}, semicolon)) + "\n");
274 ✗ System.fflush();
275 then
276 ();
277
278 else ();
279
280 end matchcontinue;
281 end showStatement;
282
283 protected function getEcho
284 "Return echo variable, which determines
285 if result should be printed or not."
286 output Boolean outBoolean;
287 algorithm
288 18871 outBoolean := 0 <> Settings.getEcho();
289 end getEcho;
290
291 protected function evaluate2
292 "Helper function to evaluate."
293 input GlobalScript.Statement inStatement;
294 output String outString;
295 protected
296 String str, str_1;
297 Absyn.AlgorithmItem algitem;
298 Absyn.Exp exp;
299 SourceInfo info;
300 algorithm
301 try /* Stack overflow */
302 outString := match inStatement
303 // Evaluate algorithm statements in evaluateAlgStmt()
304 case GlobalScript.IALG(algItem = algitem as Absyn.ALGORITHMITEM())
305 algorithm
306 5171 InstHashTable.init();
307 5171 then
308 evaluateAlgItem(algitem);
309
310 // Evaluate expressions in evaluate_exprToStr()
311 case GlobalScript.IEXP(exp = exp, info = info)
312 algorithm
313 13706 InstHashTable.init();
314 13706 then
315 evaluateExprToStr(exp, info);
316 end match;
317 else
318 str := "";
319 str_1 := "";
320 ✗ GCExt.gcollect();
321 ✗ str := StackOverflow.getReadableMessage();
322 ✗ if Testsuite.isRunning() then
323 /* It's useful to print the name of the component we failed on.
324 * But we crash in different places, so for the testsuite we skip this.
325 */
326 ✗ Error.clearCurrentComponent();
327 end if;
328 ✗ str_1 := StackOverflow.outOfMemoryMessage();
329 ✗ if stringEmpty(str_1) then
330 ✗ Error.addMessage(Error.STACK_OVERFLOW_DETAILED, {GlobalScriptDump.printIstmtStr(inStatement), str});
331 else
332 ✗ Error.addMessage(Error.OUT_OF_MEMORY_DETAILED, {GlobalScriptDump.printIstmtStr(inStatement), str_1, str});
333 end if;
334 ✗ Error.clearCurrentComponent();
335 outString := "";
336 end try annotation(__OpenModelica_stackOverflowCheckpoint=true);
337 end evaluate2;
338
339 protected function evaluateAlgItem
340 "This function takes an AlgorithmItem, i.e. a statement located in an
341 algorithm section, and a symboltable as input arguments. The statements
342 are recursivly evalutated and a new interactive symbol table is returned."
343 input Absyn.AlgorithmItem alg;
344 output String result;
345 algorithm
346 result := match alg
347 13099 case Absyn.AlgorithmItem.ALGORITHMITEM() then evaluateAlgStmt(alg.algorithm_, alg.info);
348 else "";
349 end match;
350 end evaluateAlgItem;
351
352 protected function evaluateAlgStmt
353 input Absyn.Algorithm alg;
354 input SourceInfo info;
355 output String result;
356 protected
357 FCore.Graph env;
358 FCore.Cache cache;
359 Absyn.Exp cond, msg, exp;
360 DAE.Exp dcond, dmsg, dexp;
361 String str, ident;
362 Absyn.ComponentRef cr;
363 Values.Value value;
364 list<Values.Value> values;
365 DAE.Type ty;
366 list<Absyn.Subscript> subs;
367 list<DAE.Subscript> dsubs;
368 list<Absyn.Exp> expl;
369 DAE.Properties prop;
370 list<DAE.Type> types;
371 list<DAE.ComponentRef> crefs;
372 list<tuple<Absyn.Exp, list<Absyn.AlgorithmItem>>> branches;
373 Values.Value startv, stepv, stopv;
374 Absyn.Exp starte, stepe, stope;
375 algorithm
376 result := matchcontinue alg
377 case Absyn.ALG_NORETCALL(functionCall = Absyn.CREF_IDENT(name = "assert"),
378 functionArgs = Absyn.FUNCTIONARGS(args = {cond,_}))
379 algorithm
380 ✗ env := SymbolTable.buildEnv();
381 ✗ (cache, dcond, _) := StaticScript.elabExp(FCore.emptyCache(), env, cond, true, true, DAE.NOPRE(), info);
382 ✗ (_,Values.BOOL(true)) := CevalScript.ceval(cache,env, dcond, true, Absyn.MSG(info), 0);
383 then
384 "";
385
386 case Absyn.ALG_NORETCALL(functionCall = Absyn.CREF_IDENT(name = "assert"),
387 functionArgs = Absyn.FUNCTIONARGS(args = {_, msg}))
388 algorithm
389 ✗ env := SymbolTable.buildEnv();
390 ✗ (cache, dmsg,_) := StaticScript.elabExp(FCore.emptyCache(), env, msg, true, true, DAE.NOPRE(), info);
391 ✗ (_,Values.STRING(str)) := CevalScript.ceval(cache,env, dmsg, true, Absyn.MSG(info), 0);
392 then
393 str;
394
395 case Absyn.ALG_NORETCALL()
396 algorithm
397 2132 env := SymbolTable.buildEnv();
398 2132 exp := Absyn.CALL(alg.functionCall, alg.functionArgs, {});
399 2132 (cache, dexp) := StaticScript.elabExp(FCore.emptyCache(), env, exp, true, true, DAE.NOPRE(), info);
400 2132 CevalScript.ceval(cache, env, dexp, true, Absyn.MSG(info), 0);
401 then
402 "";
403
404 // Special case to lookup fields of records.
405 // SimulationResult, etc are not in the environment,
406 // but it's nice to be able to script them anyway
407 case Absyn.ALG_ASSIGN(assignComponent = Absyn.CREF(Absyn.CREF_IDENT(name = ident, subscripts = {})),
408 value = Absyn.CREF(cr))
409 algorithm
410 1049 value := getVariableValueLst(AbsynUtil.pathToStringList(AbsynUtil.crefToPath(cr)), SymbolTable.getVars());
411 423 str := ValuesDump.valString(value);
412 423 ty := Types.typeOfValue(value);
413 423 SymbolTable.addVar(DAE.CREF_IDENT(ident, ty, {}), value, FGraph.empty());
414 then
415 str;
416
417 case Absyn.ALG_ASSIGN(assignComponent = Absyn.CREF(Absyn.CREF_IDENT(name = ident, subscripts = subs)))
418 algorithm
419 7592 env := SymbolTable.buildEnv();
420
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 7591 times.
7592 (cache, dexp, DAE.PROP(_,_)) := StaticScript.elabExp(FCore.emptyCache(), env, alg.value, true, true, DAE.NOPRE(), info);
421 7591 (_, value) := CevalScript.ceval(cache, env, dexp, true, Absyn.MSG(info), 0);
422 7590 (_, dsubs, _) := Static.elabSubscripts(cache, env, subs, true, DAE.NOPRE(), info);
423
424 7590 ty := Types.typeOfValue(value) "This type can be more specific than the elaborated type; if the dimensions are unknown...";
425 7590 str := ValuesDump.valString(value);
426 7590 SymbolTable.addVar(DAE.CREF_IDENT(ident, ty, dsubs), value, env);
427 then
428 str;
429
430 // Since expressions cannot be tuples an empty string is returned
431 case Absyn.ALG_ASSIGN(assignComponent = Absyn.TUPLE(expressions = expl))
432 algorithm
433 468 env := SymbolTable.buildEnv();
434 468 (cache, dexp, prop) := StaticScript.elabExp(FCore.emptyCache(), env, alg.value, true, true, DAE.NOPRE(), info);
435
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 468 times.
468 DAE.T_TUPLE(types = types) := Types.getPropType(prop);
436 468 crefs := makeTupleCrefs(expl, types, env, cache, info);
437
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 468 times.
468 (_, Values.TUPLE(values)) := CevalScript.ceval(cache, env, dexp, true, Absyn.MSG(info), 0);
438 468 SymbolTable.addVars(crefs, values, env);
439 then "";
440
441 // if statement
442 case Absyn.ALG_IF()
443 algorithm
444 2451 branches := (alg.ifExp, alg.trueBranch) :: alg.elseIfAlgorithmBranch;
445 2451 branches := List.appendElt((Absyn.BOOL(true), alg.elseBranch), branches);
446 2451 evaluateIfStatementLst(branches, info);
447 then
448 "";
449
450 // while-statement
451 case Absyn.ALG_WHILE()
452 algorithm
453 2 value := evaluateExpr(alg.boolExpr, info);
454 2 evaluateWhileStmt(value, alg.boolExpr, alg.whileBody, info);
455 then
456 "";
457
458 // for-statement, optimized case, e.g.: for i in 1:1000 loop
459 case Absyn.ALG_FOR(iterators = {Absyn.ITERATOR(ident, NONE(), SOME(Absyn.RANGE(start=starte, step=NONE(), stop=stope)))})
460 algorithm
461 2 startv := evaluateExpr(starte, info);
462 2 stopv := evaluateExpr(stope, info);
463 2 evaluateForStmtRangeOpt(ident, startv, Values.INTEGER(1), stopv, alg.forBody);
464 then
465 "";
466
467 // for-statement, optimized case, e.g.: for i in 7.3:0.4:1000.3 loop
468 case Absyn.ALG_FOR(iterators = {Absyn.ITERATOR(ident, NONE(), SOME(Absyn.RANGE(start=starte, step=SOME(stepe), stop=stope)))})
469 algorithm
470 4 startv := evaluateExpr(starte, info);
471 4 stepv := evaluateExpr(stepe, info);
472 4 stopv := evaluateExpr(stope, info);
473 4 evaluateForStmtRangeOpt(ident, startv, stepv, stopv, alg.forBody);
474 then
475 "";
476
477 // for-statement, general case
478 case Absyn.ALG_FOR(iterators = {Absyn.ITERATOR(ident, NONE(), SOME(exp))})
479 algorithm
480
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 24 times.
25 Values.ARRAY(valueLst = values) := evaluateExpr(exp, info);
481 24 evaluateForStmt(ident, values, alg.forBody);
482 then
483 "";
484
485 // for-statement - not an array type
486 case Absyn.ALG_FOR(iterators = {Absyn.ITERATOR(range = SOME(exp))})
487 algorithm
488 1 str := stringRepresOfExpr(exp);
489 1 Error.addSourceMessage(Error.NOT_ARRAY_TYPE_IN_FOR_STATEMENT, {str}, info);
490 1 then
491 fail();
492 end matchcontinue;
493 end evaluateAlgStmt;
494
495 protected function evaluateForStmt
496 "evaluates a for-statement in an algorithm section"
497 input String iter "The iterator variable which will be assigned different values";
498 input list<Values.Value> valList "List of values that the iterator later will be assigned to";
499 input list<Absyn.AlgorithmItem> algItemList;
500 algorithm
501
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 24 times.
99 for val in valList loop
502 75 SymbolTable.appendVar(iter, val, Types.typeOfValue(val));
503 75 evaluateAlgStmtLst(algItemList);
504 75 SymbolTable.deleteVarFirstEntry(iter);
505 end for;
506 end evaluateForStmt;
507
508 protected function evaluateForStmtRangeOpt
509 "Optimized version of for statement. In this case, we do not create a large array if
510 a range expression is given. E.g. for i in 1:10000 loop"
511 input String iter "The iterator variable which will be assigned different values";
512 input Values.Value startVal;
513 input Values.Value stepVal;
514 input Values.Value stopVal;
515 input list<Absyn.AlgorithmItem> algItems;
516 protected
517 Values.Value val;
518 algorithm
519 val := startVal;
520 try
521
2/2
✓ Branch 1 taken 1034 times.
✓ Branch 2 taken 6 times.
1040 while ValuesUtil.safeLessEq(val, stopVal) loop
522 1034 SymbolTable.appendVar(iter, val, Types.typeOfValue(val));
523 1034 evaluateAlgStmtLst(algItems);
524 1034 SymbolTable.deleteVarFirstEntry(iter);
525 1034 val := ValuesUtil.safeIntRealOp(val, stepVal, Values.ADDOP());
526 end while;
527 else
528 // Just... ignore errors and stop the loop. Really bad, I know...
529 end try;
530 end evaluateForStmtRangeOpt;
531
532 protected function evaluateWhileStmt
533 "Recursively evaluates the while statement.
534 Note that it is tail-recursive, so we should result
535 in a iterative implementation."
536 input Values.Value inValue;
537 input Absyn.Exp inExp;
538 input list<Absyn.AlgorithmItem> inAbsynAlgorithmItemLst;
539 input SourceInfo info;
540 algorithm
541 () :=
542 matchcontinue (inValue, inExp, inAbsynAlgorithmItemLst)
543 local
544 Values.Value value;
545 Absyn.Exp exp;
546 list<Absyn.AlgorithmItem> algitemlst;
547 String estr,tstr;
548 DAE.Type vtype;
549
550 case (Values.BOOL(boolean = false), _, _) then ();
551
552 case (Values.BOOL(boolean = true), exp, algitemlst)
553 algorithm
554 6 evaluateAlgStmtLst(algitemlst);
555 6 value := evaluateExpr(exp, info);
556 6 evaluateWhileStmt(value, exp, algitemlst, info); /* Tail recursive */
557 then ();
558
559 // An error occured when evaluating the algorithm items
560 case (Values.BOOL(_), _, _)
561 then ();
562
563 // The condition value was not a boolean
564 case (value, exp, _)
565 algorithm
566 1 estr := stringRepresOfExpr(exp);
567 1 vtype := Types.typeOfValue(value);
568 1 tstr := TypesDump.unparseTypeNoAttr(vtype);
569 1 Error.addSourceMessage(Error.WHILE_CONDITION_TYPE_ERROR, {estr,tstr}, info);
570 1 then fail();
571
572 end matchcontinue;
573 end evaluateWhileStmt;
574
575 protected function evaluatePartOfIfStatement
576 "Evaluates one part of a if statement, i.e. one \"case\". If the condition is true, the algorithm items
577 associated with this condition are evaluated. The first argument returned is set to true if the
578 condition was evaluated to true. Fails if the value is not a boolean.
579 Note that we are sending the expression as an value, so that it does not need to be evaluated twice."
580 input Values.Value inValue;
581 input Absyn.Exp inExp;
582 input list<Absyn.AlgorithmItem> inAbsynAlgorithmItemLst;
583 input list<tuple<Absyn.Exp, list<Absyn.AlgorithmItem>>> inTplAbsynExpAbsynAlgorithmItemLstLst;
584 input SourceInfo info;
585 algorithm
586 () :=
587 matchcontinue (inValue, inExp, inAbsynAlgorithmItemLst, inTplAbsynExpAbsynAlgorithmItemLstLst)
588 local
589 list<Absyn.AlgorithmItem> algitemlst;
590 list<tuple<Absyn.Exp, list<Absyn.AlgorithmItem>>> algrest;
591 String estr,tstr;
592 DAE.Type vtype;
593 Values.Value value;
594 Absyn.Exp exp;
595
596 case (Values.BOOL(boolean = true), _, algitemlst, _)
597 algorithm
598 2450 evaluateAlgStmtLst(algitemlst);
599 then ();
600
601 case (Values.BOOL(boolean = false), _, _, algrest)
602 algorithm
603 2034 evaluateIfStatementLst(algrest, info);
604 then ();
605
606 // Report type error
607 case (value, exp, _, _)
608 algorithm
609 1 estr := stringRepresOfExpr(exp);
610 1 vtype := Types.typeOfValue(value);
611 1 tstr := TypesDump.unparseTypeNoAttr(vtype);
612 1 Error.addSourceMessage(Error.IF_CONDITION_TYPE_ERROR, {estr,tstr}, info);
613 1 then fail();
614
615 end matchcontinue;
616 end evaluatePartOfIfStatement;
617
618 protected function evaluateIfStatementLst
619 "Evaluates all parts of a if statement
620 (i.e. a list of exp statements)"
621 input list<tuple<Absyn.Exp, list<Absyn.AlgorithmItem>>> inTplAbsynExpAbsynAlgorithmItemLstLst;
622 input SourceInfo info;
623 algorithm
624 () :=
625 match inTplAbsynExpAbsynAlgorithmItemLstLst
626 local
627 Values.Value value;
628 Absyn.Exp exp;
629 list<Absyn.AlgorithmItem> algitemlst;
630 list<tuple<Absyn.Exp, list<Absyn.AlgorithmItem>>> algrest;
631
632 case {} then ();
633
634 case (exp,algitemlst) :: algrest
635 algorithm
636 4485 value := evaluateExpr(exp, info);
637 4485 evaluatePartOfIfStatement(value, exp, algitemlst, algrest, info);
638 then ();
639
640 end match;
641 end evaluateIfStatementLst;
642
643 protected function evaluateAlgStmtLst
644 " Evaluates a list of algorithm statements"
645 input list<Absyn.AlgorithmItem> inAbsynAlgorithmItemLst;
646 algorithm
647
2/2
✓ Branch 0 taken 8635 times.
✓ Branch 1 taken 3565 times.
12200 for algitem in inAbsynAlgorithmItemLst loop
648 8635 evaluateAlgItem(algitem);
649 end for;
650 end evaluateAlgStmtLst;
651
652 protected function evaluateExpr
653 " Evaluates an expression and returns its value.
654 We need to return the symbol table, since the command loadFile()
655 reads in data to the interactive environment.
656 Note that this function may fail.
657
658 Input: Absyn.Exp - Expression to be evaluated
659 Output: Values.Value - Resulting value of the expression"
660 input Absyn.Exp inExp;
661 input SourceInfo info;
662 output Values.Value outValue;
663 algorithm
664 outValue:=
665 matchcontinue inExp
666 local
667 FCore.Graph env;
668 DAE.Exp sexp;
669 Values.Value value;
670 Absyn.Exp exp;
671 FCore.Cache cache;
672 Absyn.ComponentRef cr;
673
674 // Special case to lookup fields of records.
675 // SimulationResult, etc are not in the environment, but it's nice to be able to script them anyway */
676 case Absyn.CREF(cr)
677 500 then getVariableValueLst(AbsynUtil.pathToStringList(AbsynUtil.crefToPath(cr)), SymbolTable.getVars());
678
679 case exp
680 algorithm
681 17753 env := SymbolTable.buildEnv();
682 17753 (cache,sexp,_) := StaticScript.elabExp(FCore.emptyCache(), env, exp, true, true, DAE.NOPRE(), info);
683 17731 (_,value) := CevalScript.ceval(cache, env, sexp, true, Absyn.MSG(info),0);
684 17723 then value;
685
686 end matchcontinue;
687 end evaluateExpr;
688
689 protected function stringRepresOfExpr
690 " This function returns a string representation of an expression. For example expression
691 33+22 will result in \"55\" and expression: \"my\" + \"string\" will result in \"\"my\"+\"string\"\". "
692 input Absyn.Exp exp;
693 output String estr;
694 protected
695 FCore.Graph env;
696 DAE.Exp sexp;
697 DAE.Properties prop;
698 algorithm
699 3 env := SymbolTable.buildEnv();
700 3 (_, sexp, prop) := StaticScript.elabExp(FCore.emptyCache(), env, exp, true, true, DAE.NOPRE(), Absyn.dummyInfo);
701 3 (_, sexp, prop) := Ceval.cevalIfConstant(FCore.emptyCache(), env, sexp, prop, true, Absyn.dummyInfo);
702 3 estr := ExpressionBasics.printExpStr(sexp);
703 end stringRepresOfExpr;
704
705 protected function evaluateExprToStr
706 " This function is similar to evaluateExpr, with the difference that it returns a string
707 and that it never fails. If the expression contain errors, an empty string will be returned
708 and the errors will be stated using Error.mo
709
710 Input: Absyn.Exp - Expression to be evaluated
711 Output: string - The resulting value represented as a string"
712 input Absyn.Exp inExp;
713 input SourceInfo info;
714 output String outString;
715 algorithm
716 try
717 13706 outString := ValuesDump.valString(evaluateExpr(inExp, info));
718 else
719 outString := "";
720 end try;
721 end evaluateExprToStr;
722
723 public function simulateModel
724 "simulate() against the builtin graph, not the O(program-size) env; empty/non-positive args dropped."
725 input String className;
726 input Real stopTime;
727 input Integer numberOfIntervals;
728 input Real tolerance;
729 input String method;
730 input String simflags;
731 output String result;
732 protected
733 list<Absyn.NamedArg> nargs = {};
734 Absyn.Exp callExp;
735 FCore.Graph env;
736 FCore.Cache cache;
737 DAE.Exp sexp;
738 Values.Value value;
739 algorithm
740 try
741 ✗ if not stringEmpty(simflags) then nargs := Absyn.NAMEDARG("simflags", Absyn.STRING(simflags)) :: nargs; end if;
742 ✗ if not stringEmpty(method) then nargs := Absyn.NAMEDARG("method", Absyn.STRING(method)) :: nargs; end if;
743 ✗ if tolerance > 0.0 then nargs := Absyn.NAMEDARG("tolerance", Absyn.REAL(realString(tolerance))) :: nargs; end if;
744 ✗ if numberOfIntervals > 0 then nargs := Absyn.NAMEDARG("numberOfIntervals", Absyn.INTEGER(numberOfIntervals)) :: nargs; end if;
745 ✗ if stopTime > 0.0 then nargs := Absyn.NAMEDARG("stopTime", Absyn.REAL(realString(stopTime))) :: nargs; end if;
746 ✗ callExp := Absyn.CALL(Absyn.CREF_IDENT("simulate", {}),
747 Absyn.FUNCTIONARGS({Absyn.CREF(AbsynUtil.pathToCref(Parser.stringPath(className)))}, nargs), {});
748 ✗ (_, env) := Builtin.initialGraph(FCore.emptyCache());
749 ✗ (cache, sexp, _) := StaticScript.elabExp(FCore.emptyCache(), env, callExp, true, true, DAE.NOPRE(), Absyn.dummyInfo);
750 ✗ (_, value) := CevalScript.ceval(cache, env, sexp, true, Absyn.MSG(Absyn.dummyInfo), 0);
751 ✗ result := ValuesDump.valString(value);
752 else
753 result := "";
754 end try;
755 end simulateModel;
756
757 protected function makeTupleCrefs
758 input list<Absyn.Exp> inCrefs;
759 input list<DAE.Type> inTypes;
760 input FCore.Graph inEnv;
761 input FCore.Cache inCache;
762 input SourceInfo inInfo;
763 output list<DAE.ComponentRef> outCrefs;
764 algorithm
765
7/8
✓ Branch 0 taken 1214 times.
✓ Branch 1 taken 468 times.
✓ Branch 2 taken 1214 times.
✓ Branch 3 taken 468 times.
✓ Branch 4 taken 1214 times.
✓ Branch 5 taken 468 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 468 times.
1682 outCrefs := list(makeTupleCref(c, t, inEnv, inCache, inInfo) threaded for c in inCrefs, t in inTypes);
766 end makeTupleCrefs;
767
768 protected function makeTupleCref
769 "Translates an Absyn.CREF to a DAE.CREF_IDENT."
770 input Absyn.Exp inCref;
771 input DAE.Type inType;
772 input FCore.Graph inEnv;
773 input FCore.Cache inCache;
774 input SourceInfo inInfo;
775 output DAE.ComponentRef outCref;
776 algorithm
777 outCref := match inCref
778 local
779 Absyn.Ident id;
780 list<Absyn.Subscript> asubs;
781 list<DAE.Subscript> dsubs;
782 String str;
783
784 case Absyn.CREF(componentRef = Absyn.CREF_IDENT(id, asubs))
785 algorithm
786 1214 (_, dsubs, _) := Static.elabSubscripts(inCache, inEnv, asubs, true, DAE.NOPRE(), inInfo);
787 1214 then
788 DAE.CREF_IDENT(id, inType, dsubs);
789
790 else
791 algorithm
792 ✗ str := Dump.printExpStr(inCref);
793 ✗ Error.addMessage(Error.INVALID_TUPLE_CONTENT, {str});
794 ✗ then
795 fail();
796
797 end match;
798 end makeTupleCref;
799
800 public function getTypeOfVariable
801 "Return the type of an interactive variable,
802 given a list of variables and a variable identifier."
803 input Absyn.Ident inIdent;
804 input list<InteractiveTypes.Variable> inVariableLst;
805 output DAE.Type outType;
806 protected
807 String id;
808 DAE.Type tp;
809 algorithm
810 ✗ for var in inVariableLst loop
811 ✗ InteractiveTypes.IVAR(varIdent = id,type_ = tp) := var;
812 ✗ if stringEq(inIdent, id) then
813 outType := tp;
814 ✗ return;
815 end if;
816 end for;
817 // did not find a type
818 ✗ fail();
819 end getTypeOfVariable;
820
821 protected function extractAllComponentreplacements
822 "author: x02lucpo
823 extracts all the componentreplacementrules from program.
824 This is done by extracting all the components and then
825 extracting the rules"
826 input Absyn.Program p;
827 input Absyn.Path classPath;
828 input Absyn.ComponentRef oldName;
829 input Absyn.ComponentRef newName;
830 output InteractiveTypes.ComponentReplacementRules comp_reps;
831 protected
832 InteractiveTypes.Components comps;
833 InteractiveTypes.ComponentReplacementRules comp_repsrules;
834 algorithm
835 try
836 ✗ ErrorExt.setCheckpoint("Interactive.extractAllComponentreplacements");
837 ✗ comps := extractAllComponents(p, classPath) "class in package" ;
838 // rollback errors if we succeed
839 ✗ ErrorExt.rollBack("Interactive.extractAllComponentreplacements");
840 ✗ false := isClassReadOnly(ProgramUtil.getPathedClassInProgram(classPath,p));
841 ✗ comp_repsrules := InteractiveTypes.COMPONENTREPLACEMENTRULES({InteractiveTypes.COMPONENTREPLACEMENT(classPath,oldName,newName)},1);
842 ✗ comp_reps := getComponentreplacementsrules(comps, comp_repsrules, 0);
843 else
844 // keep errors if we fail!
845 ✗ ErrorExt.delCheckpoint("Interactive.extractAllComponentreplacements");
846 ✗ fail();
847 end try;
848 end extractAllComponentreplacements;
849
850 protected function isClassReadOnly
851 "Returns the readonly attribute of a class."
852 input Absyn.Class cl;
853 output Boolean readOnly;
854 algorithm
855 readOnly := match cl
856 case Absyn.CLASS(info = SOURCEINFO(isReadOnly=readOnly)) then readOnly;
857 end match;
858 end isClassReadOnly;
859
860 public function renameComponent
861 "This function renames a component in a class."
862 input Absyn.Path classPath;
863 input Absyn.ComponentRef oldName;
864 input Absyn.ComponentRef newName;
865 input output Absyn.Program program;
866 output Values.Value result;
867 protected
868 InteractiveTypes.ComponentReplacementRules comp_reps;
869 list<Absyn.Path> paths;
870 algorithm
871 try
872 ✗ if isClassReadOnly(ProgramUtil.getPathedClassInProgram(classPath, program)) then
873 ✗ result := ValuesMake.makeCodeTypeNameStr("Error: class: " + AbsynUtil.pathString(classPath) + " is in a read only file!");
874 ✗ return;
875 end if;
876
877 ✗ comp_reps := extractAllComponentreplacements(program, classPath, oldName, newName);
878 ✗ program := renameComponentFromComponentreplacements(program, comp_reps);
879 ✗ paths := extractRenamedClassesAsStringList(comp_reps);
880 ✗ result := ValuesMake.makeCodeTypeNameArray(paths);
881 else
882 ✗ result := ValuesMake.makeBoolean(false);
883 end try;
884 end renameComponent;
885
886 public function renameComponentOnlyInClass
887 "This function renames a component ONLY in the given class"
888 input Absyn.Path classPath;
889 input Absyn.ComponentRef oldName;
890 input Absyn.ComponentRef newName;
891 input output Absyn.Program program;
892 output Values.Value result;
893 protected
894 Absyn.Class cl;
895 Absyn.Within w;
896 algorithm
897 try
898 ✗ if isClassReadOnly(ProgramUtil.getPathedClassInProgram(classPath, program)) then
899 ✗ result := ValuesMake.makeCodeTypeNameStr("Error: class: " + AbsynUtil.pathString(classPath) + " is in a read only file!");
900 ✗ return;
901 end if;
902
903 ✗ cl := ProgramUtil.getPathedClassInProgram(classPath, program);
904 ✗ cl := renameComponentInClass(cl, oldName, newName);
905 ✗ w := ProgramUtil.buildWithin(AbsynUtil.makeFullyQualified(classPath));
906 ✗ program := ProgramUtil.updateProgram(Absyn.PROGRAM({cl}, w), program);
907 ✗ result := ValuesMake.makeCodeTypeNameArray({classPath});
908 else
909 ✗ result := ValuesMake.makeBoolean(false);
910 end try;
911 end renameComponentOnlyInClass;
912
913 protected function extractRenamedClassesAsStringList
914 "Returns the list of classes changed by the given component replacement rules."
915 input InteractiveTypes.ComponentReplacementRules rules;
916 output list<Absyn.Path> outPaths = {};
917 algorithm
918 ✗ outPaths := list(rule.which1 for rule in rules.componentReplacementLst);
919 ✗ outPaths := List.uniqueOnTrue(outPaths, AbsynUtil.pathEqual);
920 end extractRenamedClassesAsStringList;
921
922 protected function renameComponentFromComponentreplacements
923 input output Absyn.Program program;
924 input InteractiveTypes.ComponentReplacementRules rules;
925 algorithm
926 ✗ for rule in rules.componentReplacementLst loop
927 ✗ (program, _, _) := AbsynUtil.traverseClasses(program, NONE(), renameComponentVisitor, rule, true);
928 end for;
929 end renameComponentFromComponentreplacements;
930
931 protected function renameComponentVisitor
932 "author: x02lucpo
933 this is a visitor for traverse class in rename components"
934 input tuple<Absyn.Class, Option<Absyn.Path>, InteractiveTypes.ComponentReplacement> inTplAbsynClassAbsynPathOptionComponentReplacement;
935 output tuple<Absyn.Class, Option<Absyn.Path>, InteractiveTypes.ComponentReplacement> outTplAbsynClassAbsynPathOptionComponentReplacement;
936 algorithm
937 outTplAbsynClassAbsynPathOptionComponentReplacement:=
938 matchcontinue inTplAbsynClassAbsynPathOptionComponentReplacement
939 local
940 Absyn.Path path_1,pa,class_id;
941 Absyn.Class class_1,class_;
942 String id;
943 Absyn.ComponentRef old_comp,new_comp;
944 InteractiveTypes.ComponentReplacement args;
945 Option<Absyn.Path> opath;
946 case ((class_ as Absyn.CLASS(name = id)),SOME(pa),InteractiveTypes.COMPONENTREPLACEMENT(which1 = class_id,the2 = old_comp,the3 = new_comp))
947 algorithm
948 ✗ path_1 := AbsynUtil.joinPaths(pa, Absyn.IDENT(id));
949 ✗ true := AbsynUtil.pathEqual(class_id, path_1);
950 ✗ class_1 := renameComponentInClass(class_, old_comp, new_comp);
951 ✗ then
952 ((class_1,SOME(pa),
953 InteractiveTypes.COMPONENTREPLACEMENT(class_id,old_comp,new_comp)));
954 case ((class_ as Absyn.CLASS(name = id)),NONE(),InteractiveTypes.COMPONENTREPLACEMENT(which1 = class_id,the2 = old_comp,the3 = new_comp))
955 algorithm
956 ✗ path_1 := Absyn.IDENT(id);
957 ✗ true := AbsynUtil.pathEqual(class_id, path_1);
958 ✗ class_1 := renameComponentInClass(class_, old_comp, new_comp);
959 ✗ then
960 ((class_1,NONE(),
961 InteractiveTypes.COMPONENTREPLACEMENT(class_id,old_comp,new_comp)));
962 ✗ case (class_,opath,args) then ((class_,opath,args));
963 end matchcontinue;
964 end renameComponentVisitor;
965
966 protected function renameComponentInClass
967 input output Absyn.Class cls;
968 input Absyn.ComponentRef oldName;
969 input Absyn.ComponentRef newName;
970 protected
971 Absyn.ClassDef body;
972 algorithm
973 () := match cls
974 case Absyn.CLASS(body = body as Absyn.PARTS())
975 algorithm
976 ✗ body.classParts := renameComponentInParts(body.classParts, oldName, newName);
977 ✗ cls.body := body;
978 then
979 ();
980
981 case Absyn.CLASS(body = body as Absyn.CLASS_EXTENDS())
982 algorithm
983 ✗ body.parts := renameComponentInParts(body.parts, oldName, newName);
984 ✗ cls.body := body;
985 then
986 ();
987
988 else ();
989 end match;
990 end renameComponentInClass;
991
992 protected function renameComponentInParts
993 "author: x02lucpo
994 helper function to renameComponentVisitor"
995 input list<Absyn.ClassPart> inAbsynClassPartLst1;
996 input Absyn.ComponentRef inComponentRef2;
997 input Absyn.ComponentRef inComponentRef3;
998 output list<Absyn.ClassPart> outAbsynClassPartLst;
999 algorithm
1000 outAbsynClassPartLst:=
1001 matchcontinue (inAbsynClassPartLst1,inComponentRef2,inComponentRef3)
1002 local
1003 list<Absyn.ClassPart> res_1,res;
1004 list<Absyn.ElementItem> elements_1,elements;
1005 Absyn.ComponentRef old_comp,new_comp;
1006 list<Absyn.EquationItem> equations_1,equations;
1007 list<Absyn.AlgorithmItem> algorithms_1,algorithms;
1008 Absyn.ExternalDecl external_decl_1,external_decl;
1009 Option<Absyn.Annotation> ano;
1010 Absyn.ClassPart a;
1011
1012 case ({},_,_) then {}; /* the old name for the component */
1013
1014 case ((Absyn.PUBLIC(contents = elements) :: res),old_comp,new_comp)
1015 algorithm
1016 ✗ res_1 := renameComponentInParts(res, old_comp, new_comp);
1017 ✗ elements_1 := renameComponentInElements(elements, old_comp, new_comp);
1018 ✗ then
1019 (Absyn.PUBLIC(elements_1) :: res_1);
1020
1021 case ((Absyn.PROTECTED(contents = elements) :: res),old_comp,new_comp)
1022 algorithm
1023 ✗ res_1 := renameComponentInParts(res, old_comp, new_comp);
1024 ✗ elements_1 := renameComponentInElements(elements, old_comp, new_comp);
1025 ✗ then
1026 (Absyn.PROTECTED(elements_1) :: res_1);
1027
1028 case ((Absyn.EQUATIONS(contents = equations) :: res),old_comp,new_comp)
1029 algorithm
1030 ✗ res_1 := renameComponentInParts(res, old_comp, new_comp);
1031 ✗ equations_1 := renameComponentInEquationList(equations, old_comp, new_comp);
1032 ✗ then
1033 (Absyn.EQUATIONS(equations_1) :: res_1);
1034
1035 case ((Absyn.INITIALEQUATIONS(contents = equations) :: res),old_comp,new_comp)
1036 algorithm
1037 ✗ res_1 := renameComponentInParts(res, old_comp, new_comp);
1038 ✗ equations_1 := renameComponentInEquationList(equations, old_comp, new_comp);
1039 ✗ then
1040 (Absyn.INITIALEQUATIONS(equations_1) :: res_1);
1041
1042 case ((Absyn.ALGORITHMS(contents = algorithms) :: res),old_comp,new_comp)
1043 algorithm
1044 ✗ res_1 := renameComponentInParts(res, old_comp, new_comp);
1045 ✗ algorithms_1 := renameComponentInAlgorithms(algorithms, old_comp, new_comp);
1046 ✗ then
1047 (Absyn.ALGORITHMS(algorithms_1) :: res_1);
1048
1049 case ((Absyn.INITIALALGORITHMS(contents = algorithms) :: res),old_comp,new_comp)
1050 algorithm
1051 ✗ res_1 := renameComponentInParts(res, old_comp, new_comp);
1052 ✗ algorithms_1 := renameComponentInAlgorithms(algorithms, old_comp, new_comp);
1053 ✗ then
1054 (Absyn.INITIALALGORITHMS(algorithms_1) :: res_1);
1055
1056 case ((Absyn.EXTERNAL(externalDecl = external_decl,annotation_ = ano) :: res),old_comp,new_comp)
1057 algorithm
1058 ✗ res_1 := renameComponentInParts(res, old_comp, new_comp);
1059 ✗ external_decl_1 := renameComponentInExternalDecl(external_decl, old_comp, new_comp);
1060 ✗ then
1061 (Absyn.EXTERNAL(external_decl_1,ano) :: res_1);
1062
1063 case ((a :: res),old_comp,new_comp)
1064 algorithm
1065 ✗ res_1 := renameComponentInParts(res, old_comp, new_comp);
1066 then
1067 (a :: res_1);
1068 end matchcontinue;
1069 end renameComponentInParts;
1070
1071 protected function renameComponentInElements
1072 "author: x02lucpo
1073 helper function to renameComponentVisitor"
1074 input list<Absyn.ElementItem> inAbsynElementItemLst1;
1075 input Absyn.ComponentRef inComponentRef2;
1076 input Absyn.ComponentRef inComponentRef3;
1077 output list<Absyn.ElementItem> outAbsynElementItemLst;
1078 algorithm
1079 outAbsynElementItemLst := matchcontinue (inAbsynElementItemLst1,inComponentRef2,inComponentRef3)
1080 local
1081 list<Absyn.ElementItem> res_1,res;
1082 Absyn.ElementSpec elementspec_1,elementspec;
1083 Absyn.ElementItem element_1,element;
1084 Boolean finalPrefix;
1085 Option<Absyn.RedeclareKeywords> redeclare_;
1086 Absyn.InnerOuter inner_outer;
1087 SourceInfo info;
1088 Option<Absyn.ConstrainClass> constrainClass;
1089 Absyn.ComponentRef old_comp,new_comp;
1090 case ({},_,_) then {}; /* the old name for the component */
1091 case ((Absyn.ELEMENTITEM(element =
1092 Absyn.ELEMENT(finalPrefix = finalPrefix,redeclareKeywords = redeclare_,innerOuter = inner_outer,
1093 specification = elementspec,info = info,constrainClass = constrainClass)) :: res),old_comp,new_comp)
1094 algorithm
1095 ✗ res_1 := renameComponentInElements(res, old_comp, new_comp);
1096 ✗ elementspec_1 := renameComponentInElementSpec(elementspec, old_comp, new_comp);
1097 ✗ element_1 := Absyn.ELEMENTITEM(
1098 Absyn.ELEMENT(finalPrefix,redeclare_,inner_outer,elementspec_1,info,
1099 constrainClass));
1100 then
1101 (element_1 :: res_1);
1102 case ((element :: res),old_comp,new_comp)
1103 algorithm
1104 ✗ res_1 := renameComponentInElements(res, old_comp, new_comp);
1105 element_1 := element;
1106 then
1107 (element_1 :: res_1);
1108 end matchcontinue;
1109 end renameComponentInElements;
1110
1111 protected function renameComponentInElementSpec
1112 "author: x02lucpo
1113 helper function to renameComponentVisitor"
1114 input Absyn.ElementSpec inElementSpec1;
1115 input Absyn.ComponentRef inComponentRef2;
1116 input Absyn.ComponentRef inComponentRef3;
1117 output Absyn.ElementSpec outElementSpec;
1118 algorithm
1119 outElementSpec := matchcontinue (inElementSpec1,inComponentRef2,inComponentRef3)
1120 local
1121 list<Absyn.ComponentItem> comps_1,comps;
1122 Absyn.ElementAttributes attr;
1123 Absyn.TypeSpec path;
1124 Absyn.ComponentRef old_comp,new_comp;
1125 case (Absyn.COMPONENTS(attributes = attr,typeSpec = path,components = comps),old_comp,new_comp) /* the old name for the component */
1126 algorithm
1127 ✗ comps_1 := renameComponentInComponentitems(comps, old_comp, new_comp);
1128 ✗ then
1129 Absyn.COMPONENTS(attr,path,comps_1);
1130 else inElementSpec1;
1131 end matchcontinue;
1132 end renameComponentInElementSpec;
1133
1134 protected function renameComponentInComponentitems
1135 "author: x02lucpo
1136 helper function to renameComponentVisitor"
1137 input list<Absyn.ComponentItem> inAbsynComponentItemLst1;
1138 input Absyn.ComponentRef inComponentRef2;
1139 input Absyn.ComponentRef inComponentRef3;
1140 output list<Absyn.ComponentItem> outAbsynComponentItemLst;
1141 algorithm
1142 outAbsynComponentItemLst := matchcontinue (inAbsynComponentItemLst1,inComponentRef2,inComponentRef3)
1143 local
1144 Absyn.Path old_comp_path,new_comp_path;
1145 String old_comp_string,new_comp_string,name;
1146 list<Absyn.ComponentItem> res_1,res;
1147 Absyn.ComponentItem comp_1,comp;
1148 list<Absyn.Subscript> arrayDim;
1149 Option<Absyn.Modification> mod;
1150 Option<Absyn.Exp> cond;
1151 Option<Absyn.Comment> comment;
1152 Absyn.ComponentRef old_comp,new_comp;
1153 case ({},_,_) then {}; /* the old name for the component */
1154 case (((Absyn.COMPONENTITEM(component =
1155 Absyn.COMPONENT(name = name,arrayDim = arrayDim,modification = mod),condition = cond,comment = comment)) :: res),old_comp,new_comp)
1156 algorithm
1157 ✗ old_comp_path := AbsynUtil.crefToPath(old_comp);
1158 ✗ old_comp_string := AbsynUtil.pathString(old_comp_path);
1159 ✗ true := stringEq(name, old_comp_string);
1160 ✗ new_comp_path := AbsynUtil.crefToPath(new_comp);
1161 ✗ new_comp_string := AbsynUtil.pathString(new_comp_path);
1162 ✗ res_1 := renameComponentInComponentitems(res, old_comp, new_comp);
1163 ✗ comp_1 := Absyn.COMPONENTITEM(Absyn.COMPONENT(new_comp_string,arrayDim,mod),cond,comment);
1164 then
1165 (comp_1 :: res_1);
1166 case (((comp as Absyn.COMPONENTITEM(component =
1167 Absyn.COMPONENT())) :: res),old_comp,new_comp)
1168 algorithm
1169 ✗ res_1 := renameComponentInComponentitems(res, old_comp, new_comp);
1170 then
1171 (comp :: res_1);
1172 else
1173 algorithm
1174 ✗ print("-Interactive.renameComponentInComponentitems failed\n");
1175 ✗ then
1176 fail();
1177 end matchcontinue;
1178 end renameComponentInComponentitems;
1179
1180 protected function renameComponentInEquationList
1181 "author: x02lucpo
1182 helper function to renameComponentVisitor"
1183 input list<Absyn.EquationItem> inAbsynEquationItemLst1;
1184 input Absyn.ComponentRef inComponentRef2;
1185 input Absyn.ComponentRef inComponentRef3;
1186 output list<Absyn.EquationItem> outAbsynEquationItemLst;
1187 algorithm
1188 outAbsynEquationItemLst := matchcontinue (inAbsynEquationItemLst1,inComponentRef2,inComponentRef3)
1189 local
1190 list<Absyn.EquationItem> res_1,res;
1191 Absyn.Equation equation_1,equation_;
1192 Option<Absyn.Comment> cmt;
1193 SourceInfo info;
1194 Absyn.ComponentRef old_comp,new_comp;
1195 Absyn.EquationItem equation_item;
1196 case ({},_,_) then {}; /* the old name for the component */
1197 case ((Absyn.EQUATIONITEM(equation_ = equation_,comment = cmt,info=info) :: res),old_comp,new_comp)
1198 algorithm
1199 ✗ res_1 := renameComponentInEquationList(res, old_comp, new_comp);
1200 ✗ equation_1 := renameComponentInEquation(equation_, old_comp, new_comp);
1201 ✗ then
1202 (Absyn.EQUATIONITEM(equation_1,cmt,info) :: res_1);
1203 case ((equation_item :: res),old_comp,new_comp)
1204 algorithm
1205 ✗ res_1 := renameComponentInEquationList(res, old_comp, new_comp);
1206 then
1207 (equation_item :: res_1);
1208 end matchcontinue;
1209 end renameComponentInEquationList;
1210
1211 protected function renameComponentInExpEquationitemList
1212 "author: x02lucpo
1213 helper function to renameComponentVisitor"
1214 input list<tuple<Absyn.Exp, list<Absyn.EquationItem>>> inTplAbsynExpAbsynEquationItemLstLst1;
1215 input Absyn.ComponentRef inComponentRef2;
1216 input Absyn.ComponentRef inComponentRef3;
1217 output list<tuple<Absyn.Exp, list<Absyn.EquationItem>>> outTplAbsynExpAbsynEquationItemLstLst;
1218 algorithm
1219 outTplAbsynExpAbsynEquationItemLstLst := matchcontinue (inTplAbsynExpAbsynEquationItemLstLst1,inComponentRef2,inComponentRef3)
1220 local
1221 Absyn.Exp exp1_1,exp1;
1222 list<Absyn.EquationItem> eqn_item_1,eqn_item;
1223 list<tuple<Absyn.Exp, list<Absyn.EquationItem>>> res_1,res;
1224 Absyn.ComponentRef old_comp,new_comp;
1225 case ({},_,_) then {};
1226 case (((exp1,eqn_item) :: res),old_comp,new_comp)
1227 algorithm
1228 ✗ exp1_1 := renameComponentInExp(exp1, old_comp, new_comp);
1229 ✗ eqn_item_1 := renameComponentInEquationList(eqn_item, old_comp, new_comp);
1230 ✗ res_1 := renameComponentInExpEquationitemList(res, old_comp, new_comp);
1231 ✗ then
1232 ((exp1_1,eqn_item_1) :: res_1);
1233 else
1234 algorithm
1235 ✗ print("-rename_component_in_exp_equationitem_list failed\n");
1236 ✗ then
1237 fail();
1238 end matchcontinue;
1239 end renameComponentInExpEquationitemList;
1240
1241 protected function renameComponentInEquation
1242 "author: x02lucpo
1243 helper function to renameComponentVisitor"
1244 input Absyn.Equation inEquation1;
1245 input Absyn.ComponentRef inComponentRef2;
1246 input Absyn.ComponentRef inComponentRef3;
1247 output Absyn.Equation outEquation;
1248 algorithm
1249 outEquation := matchcontinue (inEquation1,inComponentRef2,inComponentRef3)
1250 local
1251 Absyn.Exp exp_1,exp,exp1_1,exp2_1,exp1,exp2;
1252 list<Absyn.EquationItem> true_items_1,elses_1,true_items,elses,equations_1,equations;
1253 list<tuple<Absyn.Exp, list<Absyn.EquationItem>>> exp_elseifs_1,exp_elseifs,exp_equations_1,exp_equations;
1254 Absyn.ComponentRef old_comp,new_comp,cref1_1,cref2_1,cref1,cref2,cref;
1255 String ident;
1256 Absyn.FunctionArgs function_args;
1257 /* the old name for the component */
1258 case (Absyn.EQ_IF(ifExp = exp,equationTrueItems = true_items,elseIfBranches = exp_elseifs,equationElseItems = elses),old_comp,new_comp)
1259 algorithm
1260 ✗ exp_1 := renameComponentInExp(exp, old_comp, new_comp);
1261 ✗ true_items_1 := renameComponentInEquationList(true_items, old_comp, new_comp);
1262 ✗ exp_elseifs_1 := renameComponentInExpEquationitemList(exp_elseifs, old_comp, new_comp);
1263 ✗ elses_1 := renameComponentInEquationList(elses, old_comp, new_comp);
1264 ✗ then
1265 Absyn.EQ_IF(exp_1,true_items_1,exp_elseifs_1,elses_1);
1266 case (Absyn.EQ_EQUALS(leftSide = exp1,rightSide = exp2),old_comp,new_comp)
1267 algorithm
1268 ✗ exp1_1 := renameComponentInExp(exp1, old_comp, new_comp);
1269 ✗ exp2_1 := renameComponentInExp(exp2, old_comp, new_comp);
1270 ✗ then
1271 Absyn.EQ_EQUALS(exp1_1,exp2_1);
1272 case (Absyn.EQ_PDE(leftSide = exp1,rightSide = exp2,domain = cref1),old_comp,new_comp)
1273 algorithm
1274 ✗ exp1_1 := renameComponentInExp(exp1, old_comp, new_comp);
1275 ✗ exp2_1 := renameComponentInExp(exp2, old_comp, new_comp);
1276 ✗ cref1_1 := replaceStartInComponentRef(cref1, old_comp, new_comp);
1277 ✗ then
1278 Absyn.EQ_PDE(exp1_1,exp2_1,cref1_1);
1279 case (Absyn.EQ_CONNECT(connector1 = cref1,connector2 = cref2),old_comp,new_comp)
1280 algorithm
1281 ✗ cref1_1 := replaceStartInComponentRef(cref1, old_comp, new_comp);
1282 ✗ cref2_1 := replaceStartInComponentRef(cref2, old_comp, new_comp) "print \"-rename_component_in_equation EQ_CONNECT not implemented yet\\n\"" ;
1283 ✗ then
1284 Absyn.EQ_CONNECT(cref1_1,cref2_1);
1285 case (Absyn.EQ_FOR(iterators = {Absyn.ITERATOR(ident,NONE(),SOME(exp))},forEquations = equations),old_comp,new_comp)
1286 algorithm
1287 ✗ exp_1 := renameComponentInExp(exp, old_comp, new_comp);
1288 ✗ equations_1 := renameComponentInEquationList(equations, old_comp, new_comp);
1289 ✗ then
1290 Absyn.EQ_FOR({Absyn.ITERATOR(ident,NONE(),SOME(exp_1))},equations_1);
1291 case (Absyn.EQ_WHEN_E(whenExp = exp,whenEquations = equations,elseWhenEquations = exp_equations),old_comp,new_comp)
1292 algorithm
1293 ✗ exp_1 := renameComponentInExp(exp, old_comp, new_comp);
1294 ✗ equations_1 := renameComponentInEquationList(equations, old_comp, new_comp);
1295 ✗ exp_equations_1 := renameComponentInExpEquationitemList(exp_equations, old_comp, new_comp);
1296 ✗ then
1297 Absyn.EQ_WHEN_E(exp_1,equations_1,exp_equations_1);
1298 case (Absyn.EQ_NORETCALL(functionName = cref,functionArgs = function_args),_,_)
1299 algorithm
1300 ✗ print("-rename_component_in_equation EQ_NORETCALL not implemented yet\n");
1301 ✗ then
1302 Absyn.EQ_NORETCALL(cref,function_args);
1303 else
1304 algorithm
1305 ✗ print("-rename_component_in_equation failed\n");
1306 ✗ then
1307 fail();
1308 end matchcontinue;
1309 end renameComponentInEquation;
1310
1311 protected function renameComponentInExpList
1312 "author: x02lucpo
1313 helper function to renameComponentVisitor"
1314 input list<Absyn.Exp> inAbsynExpLst1;
1315 input Absyn.ComponentRef inComponentRef2;
1316 input Absyn.ComponentRef inComponentRef3;
1317 output list<Absyn.Exp> outAbsynExpLst;
1318 algorithm
1319 outAbsynExpLst := matchcontinue (inAbsynExpLst1,inComponentRef2,inComponentRef3)
1320 local
1321 Absyn.Exp exp_1,exp;
1322 list<Absyn.Exp> res_1,res;
1323 Absyn.ComponentRef old_comp,new_comp;
1324 case ({},_,_) then {}; /* the old name for the component */
1325 case ((exp :: res),old_comp,new_comp)
1326 algorithm
1327 ✗ exp_1 := renameComponentInExp(exp, old_comp, new_comp);
1328 ✗ res_1 := renameComponentInExpList(res, old_comp, new_comp);
1329 then
1330 (exp_1 :: res_1);
1331 else
1332 algorithm
1333 ✗ print("-rename_component_in_exp_list failed\n");
1334 ✗ then
1335 fail();
1336 end matchcontinue;
1337 end renameComponentInExpList;
1338
1339 protected function renameComponentInExpListList
1340 "author: x02lucpo
1341 helper function to renameComponentVisitor"
1342 input list<list<Absyn.Exp>> inAbsynExpLstLst1;
1343 input Absyn.ComponentRef inComponentRef2;
1344 input Absyn.ComponentRef inComponentRef3;
1345 output list<list<Absyn.Exp>> outAbsynExpLstLst;
1346 algorithm
1347 outAbsynExpLstLst := matchcontinue (inAbsynExpLstLst1,inComponentRef2,inComponentRef3)
1348 local
1349 list<Absyn.Exp> exp_1,exp;
1350 list<list<Absyn.Exp>> res_1,res;
1351 Absyn.ComponentRef old_comp,new_comp;
1352 case ({},_,_) then {}; /* the old name for the component */
1353 case ((exp :: res),old_comp,new_comp)
1354 algorithm
1355 ✗ exp_1 := renameComponentInExpList(exp, old_comp, new_comp);
1356 ✗ res_1 := renameComponentInExpListList(res, old_comp, new_comp);
1357 then
1358 (exp_1 :: res_1);
1359 else
1360 algorithm
1361 ✗ print("-rename_component_in_exp_list_list failed\n");
1362 ✗ then
1363 fail();
1364 end matchcontinue;
1365 end renameComponentInExpListList;
1366
1367 protected function renameComponentInExpTupleList
1368 "author: x02lucpo
1369 helper function to renameComponentVisitor"
1370 input list<tuple<Absyn.Exp, Absyn.Exp>> inTplAbsynExpAbsynExpLst1;
1371 input Absyn.ComponentRef inComponentRef2;
1372 input Absyn.ComponentRef inComponentRef3;
1373 output list<tuple<Absyn.Exp, Absyn.Exp>> outTplAbsynExpAbsynExpLst;
1374 algorithm
1375 outTplAbsynExpAbsynExpLst := matchcontinue (inTplAbsynExpAbsynExpLst1,inComponentRef2,inComponentRef3)
1376 local
1377 Absyn.Exp exp1_1,exp2_1,exp1,exp2;
1378 list<tuple<Absyn.Exp, Absyn.Exp>> res_1,res;
1379 Absyn.ComponentRef old_comp,new_comp;
1380 case ({},_,_) then {};
1381 case (((exp1,exp2) :: res),old_comp,new_comp)
1382 algorithm
1383 ✗ exp1_1 := renameComponentInExp(exp1, old_comp, new_comp);
1384 ✗ exp2_1 := renameComponentInExp(exp2, old_comp, new_comp);
1385 ✗ res_1 := renameComponentInExpTupleList(res, old_comp, new_comp);
1386 ✗ then
1387 ((exp1_1,exp2_1) :: res_1);
1388 else
1389 algorithm
1390 ✗ print("-rename_component_in_exp_tuple_list failed\n");
1391 ✗ then
1392 fail();
1393 end matchcontinue;
1394 end renameComponentInExpTupleList;
1395
1396 protected function renameComponentInElementArgList
1397 "author: x02lucpo
1398 helper function to renameComponentVisitor"
1399 input list<Absyn.ElementArg> inAbsynElementArgLst1;
1400 input Absyn.ComponentRef inComponentRef2;
1401 input Absyn.ComponentRef inComponentRef3;
1402 output list<Absyn.ElementArg> outAbsynElementArgLst;
1403 algorithm
1404 outAbsynElementArgLst := matchcontinue (inAbsynElementArgLst1,inComponentRef2,inComponentRef3)
1405 local
1406 Absyn.ElementArg element_arg_1,element_arg;
1407 list<Absyn.ElementArg> res_1,res;
1408 Absyn.ComponentRef old_comp,new_comp;
1409 case ({},_,_) then {}; /* the old name for the component */
1410 case ((element_arg :: res),old_comp,new_comp)
1411 algorithm
1412 ✗ element_arg_1 := renameComponentInElementArg(element_arg, old_comp, new_comp);
1413 ✗ res_1 := renameComponentInElementArgList(res, old_comp, new_comp);
1414 then
1415 (element_arg_1 :: res_1);
1416 else
1417 algorithm
1418 ✗ print("-rename_component_in_element_arg_list failed\n");
1419 ✗ then
1420 fail();
1421 end matchcontinue;
1422 end renameComponentInElementArgList;
1423
1424 protected function renameComponentInElementArg
1425 "author: x02lucpo
1426 helper function to renameComponentVisitor"
1427 input Absyn.ElementArg inElementArg1;
1428 input Absyn.ComponentRef inComponentRef2;
1429 input Absyn.ComponentRef inComponentRef3;
1430 output Absyn.ElementArg outElementArg;
1431 algorithm
1432 outElementArg := match (inElementArg1,inComponentRef2,inComponentRef3)
1433 local
1434 Absyn.ComponentRef old_comp,new_comp;
1435 Absyn.Path p,p_1;
1436 Absyn.Exp exp_1,exp;
1437 list<Absyn.ElementArg> element_args_1,element_args;
1438 Boolean b;
1439 Absyn.Each each_;
1440 Option<String> str;
1441 Absyn.ElementSpec element_spec_1,element_spec2_1,element_spec,element_spec2;
1442 Absyn.RedeclareKeywords redecl;
1443 Option<Absyn.Comment> c;
1444 SourceInfo info, mod_info;
1445 /* the old name for the component */
1446 case (Absyn.MODIFICATION(finalPrefix = b,eachPrefix = each_,path = p,modification = SOME(Absyn.CLASSMOD(element_args,Absyn.EQMOD(exp,info))),comment = str,info = mod_info),old_comp,new_comp)
1447 algorithm
1448 ✗ p_1 := AbsynUtil.crefToPath(replaceStartInComponentRef(AbsynUtil.pathToCref(p), old_comp, new_comp));
1449 ✗ exp_1 := renameComponentInExp(exp, old_comp, new_comp);
1450 ✗ element_args_1 := renameComponentInElementArgList(element_args, old_comp, new_comp);
1451 ✗ then
1452 Absyn.MODIFICATION(b,each_,p_1,
1453 SOME(Absyn.CLASSMOD(element_args_1,Absyn.EQMOD(exp_1,info))),str,mod_info);
1454 case (Absyn.MODIFICATION(finalPrefix = b,eachPrefix = each_,path = p,modification = SOME(Absyn.CLASSMOD(element_args,Absyn.NOMOD())),comment = str, info = mod_info),old_comp,new_comp)
1455 algorithm
1456 ✗ p_1 := AbsynUtil.crefToPath(replaceStartInComponentRef(AbsynUtil.pathToCref(p), old_comp, new_comp));
1457 ✗ element_args_1 := renameComponentInElementArgList(element_args, old_comp, new_comp);
1458 ✗ then
1459 Absyn.MODIFICATION(b,each_,p_1,SOME(Absyn.CLASSMOD(element_args_1,Absyn.NOMOD())),str,mod_info);
1460 case (Absyn.MODIFICATION(finalPrefix = b,eachPrefix = each_,path = p,modification = NONE(),comment = str, info = mod_info),old_comp,new_comp)
1461 algorithm
1462 ✗ p_1 := AbsynUtil.crefToPath(replaceStartInComponentRef(AbsynUtil.pathToCref(p), old_comp, new_comp));
1463 ✗ then
1464 Absyn.MODIFICATION(b,each_,p_1,NONE(),str,mod_info);
1465 case (Absyn.REDECLARATION(finalPrefix = b,redeclareKeywords = redecl,eachPrefix = each_,elementSpec = element_spec,constrainClass = SOME(Absyn.CONSTRAINCLASS(element_spec2,c)),info = info),old_comp,new_comp)
1466 algorithm
1467 ✗ element_spec_1 := renameComponentInElementSpec(element_spec, old_comp, new_comp);
1468 ✗ element_spec2_1 := renameComponentInElementSpec(element_spec2, old_comp, new_comp);
1469 ✗ then
1470 Absyn.REDECLARATION(b,redecl,each_,element_spec_1,
1471 SOME(Absyn.CONSTRAINCLASS(element_spec2_1,c)),info);
1472 case (Absyn.REDECLARATION(finalPrefix = b,redeclareKeywords = redecl,eachPrefix = each_,elementSpec = element_spec,constrainClass = NONE(),info=info),old_comp,new_comp)
1473 algorithm
1474 ✗ element_spec_1 := renameComponentInElementSpec(element_spec, old_comp, new_comp);
1475 ✗ then
1476 Absyn.REDECLARATION(b,redecl,each_,element_spec_1,NONE(),info);
1477 end match;
1478 end renameComponentInElementArg;
1479
1480 protected function renameComponentInCode
1481 "author: x02lucpo
1482 helper function to renameComponentVisitor"
1483 input Absyn.CodeNode inCode1;
1484 input Absyn.ComponentRef inComponentRef2;
1485 input Absyn.ComponentRef inComponentRef3;
1486 output Absyn.CodeNode outCode;
1487 algorithm
1488 outCode := match (inCode1,inComponentRef2,inComponentRef3)
1489 local
1490 Absyn.Path path;
1491 Absyn.ComponentRef old_comp,new_comp,cr_1,cr;
1492 list<Absyn.EquationItem> eqn_items_1,eqn_items;
1493 Boolean b,finalPrefix;
1494 list<Absyn.AlgorithmItem> algs_1,algs;
1495 Absyn.ElementSpec elementspec_1,elementspec;
1496 Option<Absyn.RedeclareKeywords> redeclare_;
1497 Absyn.InnerOuter inner_outer;
1498 SourceInfo info;
1499 Option<Absyn.ConstrainClass> constrainClass;
1500 Absyn.Exp exp_1,exp;
1501 list<Absyn.ElementArg> element_args_1,element_args;
1502 ✗ case (Absyn.C_TYPENAME(path = path),_,_) then Absyn.C_TYPENAME(path); /* the old name for the component */
1503 case (Absyn.C_VARIABLENAME(componentRef = cr),old_comp,new_comp)
1504 algorithm
1505 ✗ cr_1 := replaceStartInComponentRef(cr, old_comp, new_comp);
1506 ✗ then
1507 Absyn.C_VARIABLENAME(cr_1);
1508 case (Absyn.C_EQUATIONSECTION(boolean = b,equationItemLst = eqn_items),old_comp,new_comp)
1509 algorithm
1510 ✗ eqn_items_1 := renameComponentInEquationList(eqn_items, old_comp, new_comp);
1511 ✗ then
1512 Absyn.C_EQUATIONSECTION(b,eqn_items_1);
1513 case (Absyn.C_ALGORITHMSECTION(boolean = b,algorithmItemLst = algs),old_comp,new_comp)
1514 algorithm
1515 ✗ algs_1 := renameComponentInAlgorithms(algs, old_comp, new_comp);
1516 ✗ then
1517 Absyn.C_ALGORITHMSECTION(b,algs_1);
1518 case (Absyn.C_ELEMENT(element = Absyn.ELEMENT(finalPrefix = finalPrefix,redeclareKeywords = redeclare_,innerOuter = inner_outer,specification = elementspec,info = info,constrainClass = constrainClass)),old_comp,new_comp)
1519 algorithm
1520 ✗ elementspec_1 := renameComponentInElementSpec(elementspec, old_comp, new_comp);
1521 ✗ then
1522 Absyn.C_ELEMENT(
1523 Absyn.ELEMENT(finalPrefix,redeclare_,inner_outer,elementspec_1,info,
1524 constrainClass));
1525 case (Absyn.C_EXPRESSION(exp = exp),old_comp,new_comp)
1526 algorithm
1527 ✗ exp_1 := renameComponentInExp(exp, old_comp, new_comp);
1528 ✗ then
1529 Absyn.C_EXPRESSION(exp_1);
1530 case (Absyn.C_MODIFICATION(modification = Absyn.CLASSMOD(elementArgLst = element_args,eqMod = Absyn.EQMOD(exp,info))),old_comp,new_comp)
1531 algorithm
1532 ✗ exp_1 := renameComponentInExp(exp, old_comp, new_comp);
1533 ✗ element_args_1 := renameComponentInElementArgList(element_args, old_comp, new_comp);
1534 ✗ then
1535 Absyn.C_MODIFICATION(Absyn.CLASSMOD(element_args_1,Absyn.EQMOD(exp_1,info)));
1536 case (Absyn.C_MODIFICATION(modification = Absyn.CLASSMOD(elementArgLst = element_args,eqMod = Absyn.NOMOD())),old_comp,new_comp)
1537 algorithm
1538 ✗ element_args_1 := renameComponentInElementArgList(element_args, old_comp, new_comp);
1539 ✗ then
1540 Absyn.C_MODIFICATION(Absyn.CLASSMOD(element_args_1,Absyn.NOMOD()));
1541 end match;
1542 end renameComponentInCode;
1543
1544 protected function renameComponentInExp
1545 "author: x02lucpo
1546 helper function to renameComponentVisitor"
1547 input Absyn.Exp inExp1;
1548 input Absyn.ComponentRef oldPrefix;
1549 input Absyn.ComponentRef newPrefix;
1550 output Absyn.Exp outExp;
1551 algorithm
1552 outExp:=
1553 matchcontinue (inExp1, oldPrefix, newPrefix)
1554 local
1555 Absyn.ComponentRef old_comp,new_comp,cr_1,cr,cref;
1556 Absyn.Exp exp1_1,exp2_1,exp1,exp2,exp,exp3_1,exp3;
1557 Absyn.Operator op;
1558 list<tuple<Absyn.Exp, Absyn.Exp>> exp_tuple_list_1,exp_tuple_list;
1559 Absyn.FunctionArgs func_args;
1560 list<Absyn.Exp> exp_list_1,exp_list;
1561 list<list<Absyn.Exp>> exp_list_list_1,exp_list_list;
1562 Absyn.CodeNode code_1,code;
1563 case (Absyn.INTEGER(),_,_) then inExp1;
1564 case (Absyn.REAL(),_,_) then inExp1;
1565 case (Absyn.CREF(componentRef = cr),old_comp,new_comp)
1566 algorithm
1567 ✗ cr_1 := replaceStartInComponentRef(cr, old_comp, new_comp);
1568 ✗ then
1569 Absyn.CREF(cr_1);
1570 case (Absyn.STRING(),_,_) then inExp1;
1571 case (Absyn.BOOL(),_,_) then inExp1;
1572 case (Absyn.BINARY(exp1 = exp1,op = op,exp2 = exp2),old_comp,new_comp)
1573 algorithm
1574 ✗ exp1_1 := renameComponentInExp(exp1, old_comp, new_comp);
1575 ✗ exp2_1 := renameComponentInExp(exp2, old_comp, new_comp);
1576 ✗ then
1577 Absyn.BINARY(exp1_1,op,exp2_1);
1578 case (Absyn.UNARY(op = op,exp = exp),old_comp,new_comp)
1579 algorithm
1580 ✗ exp := renameComponentInExp(exp, old_comp, new_comp); // TODO: Update the expression?
1581 ✗ then
1582 Absyn.UNARY(op,exp);
1583 case (Absyn.LBINARY(exp1 = exp1,op = op,exp2 = exp2),old_comp,new_comp)
1584 algorithm
1585 ✗ exp1_1 := renameComponentInExp(exp1, old_comp, new_comp);
1586 ✗ exp2_1 := renameComponentInExp(exp2, old_comp, new_comp);
1587 ✗ then
1588 Absyn.LBINARY(exp1_1,op,exp2_1);
1589 case (Absyn.LUNARY(op = op,exp = exp),old_comp,new_comp)
1590 algorithm
1591 ✗ exp := renameComponentInExp(exp, old_comp, new_comp); // TODO: Update the expression?
1592 ✗ then
1593 Absyn.LUNARY(op,exp);
1594 case (Absyn.RELATION(exp1 = exp1,op = op,exp2 = exp2),old_comp,new_comp)
1595 algorithm
1596 ✗ exp1_1 := renameComponentInExp(exp1, old_comp, new_comp);
1597 ✗ exp2_1 := renameComponentInExp(exp2, old_comp, new_comp);
1598 ✗ then
1599 Absyn.RELATION(exp1_1,op,exp2_1);
1600 case (Absyn.IFEXP(ifExp = exp1,trueBranch = exp2,elseBranch = exp3,elseIfBranch = exp_tuple_list),old_comp,new_comp)
1601 algorithm
1602 ✗ exp1_1 := renameComponentInExp(exp1, old_comp, new_comp);
1603 ✗ exp2_1 := renameComponentInExp(exp2, old_comp, new_comp);
1604 ✗ exp3_1 := renameComponentInExp(exp3, old_comp, new_comp);
1605 ✗ exp_tuple_list_1 := renameComponentInExpTupleList(exp_tuple_list, old_comp, new_comp);
1606 ✗ then
1607 Absyn.IFEXP(exp1_1,exp2_1,exp3_1,exp_tuple_list_1);
1608 case (Absyn.CALL(function_ = cref,functionArgs = func_args), old_comp, new_comp)
1609 algorithm
1610 ✗ cref := replaceStartInComponentRef(cref, old_comp, new_comp);
1611 ✗ func_args := renameComponentInFunctionArgs(func_args, old_comp, new_comp);
1612 ✗ then
1613 Absyn.CALL(cref,func_args,inExp1.typeVars);
1614 case (Absyn.ARRAY(arrayExp = exp_list),old_comp,new_comp)
1615 algorithm
1616 ✗ exp_list_1 := renameComponentInExpList(exp_list, old_comp, new_comp);
1617 ✗ then
1618 Absyn.ARRAY(exp_list_1);
1619 case (Absyn.MATRIX(matrix = exp_list_list),old_comp,new_comp)
1620 algorithm
1621 ✗ exp_list_list_1 := renameComponentInExpListList(exp_list_list, old_comp, new_comp);
1622 ✗ then
1623 Absyn.MATRIX(exp_list_list_1);
1624 case (Absyn.RANGE(start = exp1,step = SOME(exp2),stop = exp3),old_comp,new_comp)
1625 algorithm
1626 ✗ exp1_1 := renameComponentInExp(exp1, old_comp, new_comp);
1627 ✗ exp2_1 := renameComponentInExp(exp2, old_comp, new_comp);
1628 ✗ exp3_1 := renameComponentInExp(exp3, old_comp, new_comp);
1629 ✗ then
1630 Absyn.RANGE(exp1_1,SOME(exp2_1),exp3_1);
1631 case (Absyn.RANGE(start = exp1,step = NONE(),stop = exp3),old_comp,new_comp)
1632 algorithm
1633 ✗ exp1_1 := renameComponentInExp(exp1, old_comp, new_comp);
1634 ✗ exp3_1 := renameComponentInExp(exp3, old_comp, new_comp);
1635 ✗ then
1636 Absyn.RANGE(exp1_1,NONE(),exp3_1);
1637 case (Absyn.TUPLE(expressions = exp_list),old_comp,new_comp)
1638 algorithm
1639 ✗ exp_list_1 := renameComponentInExpList(exp_list, old_comp, new_comp);
1640 ✗ then
1641 Absyn.TUPLE(exp_list_1);
1642 case (Absyn.END(),_,_) then Absyn.END();
1643 case (Absyn.CODE(code = code),old_comp,new_comp)
1644 algorithm
1645 ✗ code_1 := renameComponentInCode(code, old_comp, new_comp);
1646 ✗ then
1647 Absyn.CODE(code_1);
1648 else
1649 algorithm
1650 ✗ print("-rename_component_in_exp failed\n");
1651 ✗ then
1652 fail();
1653 end matchcontinue;
1654 end renameComponentInExp;
1655
1656 protected function renameComponentInAlgorithms
1657 "author: x02lucpo
1658 helper function to renameComponentVisitor"
1659 input list<Absyn.AlgorithmItem> inAbsynAlgorithmItemLst1;
1660 input Absyn.ComponentRef inComponentRef2;
1661 input Absyn.ComponentRef inComponentRef3;
1662 output list<Absyn.AlgorithmItem> outAbsynAlgorithmItemLst;
1663 algorithm
1664 outAbsynAlgorithmItemLst:=
1665 match (inAbsynAlgorithmItemLst1,inComponentRef2,inComponentRef3)
1666 local
1667 list<Absyn.AlgorithmItem> res_1,res;
1668 Absyn.AlgorithmItem algorithm_1,algorithm_;
1669 Absyn.ComponentRef old_comp,new_comp;
1670 case ({},_,_) then {}; /* the old name for the component */
1671 case ((algorithm_ :: res),old_comp,new_comp)
1672 algorithm
1673 ✗ res_1 := renameComponentInAlgorithms(res, old_comp, new_comp);
1674 algorithm_1 := algorithm_;
1675 then
1676 (algorithm_1 :: res_1);
1677 end match;
1678 end renameComponentInAlgorithms;
1679
1680 protected function renameComponentInAlgorithm
1681 "author: x02lucpo
1682 helper function to renameComponentVisitor"
1683 input Absyn.Algorithm inAlgorithm1;
1684 input Absyn.ComponentRef inComponentRef2;
1685 input Absyn.ComponentRef inComponentRef3;
1686 output Absyn.Algorithm outAlgorithm;
1687 algorithm
1688 outAlgorithm:=
1689 match (inAlgorithm1,inComponentRef2,inComponentRef3)
1690 local
1691 Absyn.ComponentRef cr_1,cr,old_comp,new_comp;
1692 Absyn.Exp exp_1,exp,exp1_1,exp2_1,exp1,exp2;
1693 list<Absyn.AlgorithmItem> algs1_1,algs2_1,algs1,algs2,algs_1,algs;
1694 list<tuple<Absyn.Exp, list<Absyn.AlgorithmItem>>> exp_algs_list_1,exp_algs_list;
1695 String id;
1696 Absyn.FunctionArgs func_args_1,func_args;
1697 case (Absyn.ALG_ASSIGN(assignComponent = Absyn.CREF(cr),value = exp),old_comp,new_comp) /* the old name for the component */
1698 algorithm
1699 ✗ cr_1 := replaceStartInComponentRef(cr, old_comp, new_comp);
1700 ✗ exp_1 := renameComponentInExp(exp, old_comp, new_comp);
1701 ✗ then
1702 Absyn.ALG_ASSIGN(Absyn.CREF(cr_1),exp_1);
1703 case (Absyn.ALG_ASSIGN(assignComponent = exp1 as Absyn.TUPLE(_),value = exp2),old_comp,new_comp)
1704 algorithm
1705 ✗ exp1_1 := renameComponentInExp(exp1, old_comp, new_comp);
1706 ✗ exp2_1 := renameComponentInExp(exp2, old_comp, new_comp);
1707 ✗ then
1708 Absyn.ALG_ASSIGN(exp1_1, exp2_1);
1709 case (Absyn.ALG_IF(ifExp = exp,trueBranch = algs1,elseIfAlgorithmBranch = exp_algs_list,elseBranch = algs2),old_comp,new_comp)
1710 algorithm
1711 ✗ exp_1 := renameComponentInExp(exp, old_comp, new_comp);
1712 ✗ algs1_1 := renameComponentInAlgorithms(algs1, old_comp, new_comp);
1713 ✗ exp_algs_list_1 := renameComponentInExpAlgoritmsList(exp_algs_list, old_comp, new_comp);
1714 ✗ algs2_1 := renameComponentInAlgorithms(algs2, old_comp, new_comp);
1715 ✗ then
1716 Absyn.ALG_IF(exp_1,algs1_1,exp_algs_list_1,algs2_1);
1717 case (Absyn.ALG_FOR(iterators = {Absyn.ITERATOR(id,NONE(),SOME(exp))},forBody = algs),old_comp,new_comp)
1718 algorithm
1719 ✗ exp_1 := renameComponentInExp(exp, old_comp, new_comp);
1720 ✗ algs_1 := renameComponentInAlgorithms(algs, old_comp, new_comp);
1721 ✗ then
1722 Absyn.ALG_FOR({Absyn.ITERATOR(id,NONE(),SOME(exp_1))},algs_1);
1723 case (Absyn.ALG_WHILE(boolExpr = exp,whileBody = algs),old_comp,new_comp)
1724 algorithm
1725 ✗ exp_1 := renameComponentInExp(exp, old_comp, new_comp);
1726 ✗ algs_1 := renameComponentInAlgorithms(algs, old_comp, new_comp);
1727 ✗ then
1728 Absyn.ALG_WHILE(exp_1,algs_1);
1729 case (Absyn.ALG_WHEN_A(boolExpr = exp,whenBody = algs,elseWhenAlgorithmBranch = exp_algs_list),old_comp,new_comp)
1730 algorithm
1731 ✗ exp_1 := renameComponentInExp(exp, old_comp, new_comp);
1732 ✗ algs_1 := renameComponentInAlgorithms(algs, old_comp, new_comp);
1733 ✗ exp_algs_list_1 := renameComponentInExpAlgoritmsList(exp_algs_list, old_comp, new_comp);
1734 ✗ then
1735 Absyn.ALG_WHEN_A(exp_1,algs_1,exp_algs_list_1);
1736 case (Absyn.ALG_NORETCALL(functionCall = cr,functionArgs = func_args),old_comp,new_comp)
1737 algorithm
1738 ✗ cr_1 := replaceStartInComponentRef(cr, old_comp, new_comp);
1739 ✗ func_args_1 := renameComponentInFunctionArgs(func_args, old_comp, new_comp);
1740 ✗ then
1741 Absyn.ALG_NORETCALL(cr_1,func_args_1);
1742 end match;
1743 end renameComponentInAlgorithm;
1744
1745 protected function renameComponentInExpAlgoritmsList
1746 "author: x02lucpo
1747 helper function to renameComponentVisitor"
1748 input list<tuple<Absyn.Exp, list<Absyn.AlgorithmItem>>> inTplAbsynExpAbsynAlgorithmItemLstLst1;
1749 input Absyn.ComponentRef inComponentRef2;
1750 input Absyn.ComponentRef inComponentRef3;
1751 output list<tuple<Absyn.Exp, list<Absyn.AlgorithmItem>>> outTplAbsynExpAbsynAlgorithmItemLstLst;
1752 algorithm
1753 outTplAbsynExpAbsynAlgorithmItemLstLst:=
1754 matchcontinue (inTplAbsynExpAbsynAlgorithmItemLstLst1,inComponentRef2,inComponentRef3)
1755 local
1756 Absyn.Exp exp_1,exp;
1757 list<Absyn.AlgorithmItem> algs_1,algs;
1758 list<tuple<Absyn.Exp, list<Absyn.AlgorithmItem>>> res_1,res;
1759 Absyn.ComponentRef old_comp,new_comp;
1760 case ({},_,_) then {};
1761 case (((exp,algs) :: res),old_comp,new_comp)
1762 algorithm
1763 ✗ exp_1 := renameComponentInExp(exp, old_comp, new_comp);
1764 ✗ algs_1 := renameComponentInAlgorithms(algs, old_comp, new_comp);
1765 ✗ res_1 := renameComponentInExpAlgoritmsList(res, old_comp, new_comp);
1766 ✗ then
1767 ((exp_1,algs_1) :: res_1);
1768 else
1769 algorithm
1770 ✗ print("-rename_component_in_exp_algoritms_list failed\n");
1771 ✗ then
1772 fail();
1773 end matchcontinue;
1774 end renameComponentInExpAlgoritmsList;
1775
1776 protected function renameComponentInFunctionArgs
1777 "author: x02lucpo
1778 helper function to renameComponentVisitor"
1779 input Absyn.FunctionArgs inFunctionArgs1;
1780 input Absyn.ComponentRef inComponentRef2;
1781 input Absyn.ComponentRef inComponentRef3;
1782 output Absyn.FunctionArgs outFunctionArgs;
1783 algorithm
1784 outFunctionArgs:=
1785 matchcontinue (inFunctionArgs1,inComponentRef2,inComponentRef3)
1786 local
1787 list<Absyn.Exp> exps_1,exps;
1788 list<Absyn.NamedArg> namedArg_1,namedArg;
1789 Absyn.ComponentRef old_comp,new_comp;
1790 Absyn.Exp exp1_1,exp;
1791 Absyn.ForIterators iterators, iteratorsRenamed;
1792 Absyn.ReductionIterType iterType;
1793 case (Absyn.FUNCTIONARGS(args = exps,argNames = namedArg),old_comp,new_comp) /* the old name for the component */
1794 algorithm
1795 ✗ exps_1 := renameComponentInExpList(exps, old_comp, new_comp);
1796 ✗ namedArg_1 := renameComponentInNamedArgs(namedArg, old_comp, new_comp);
1797 ✗ then
1798 Absyn.FUNCTIONARGS(exps_1,namedArg_1);
1799 case (Absyn.FOR_ITER_FARG(exp, iterType, iterators),old_comp,new_comp)
1800 algorithm
1801 ✗ exp1_1 := renameComponentInExp(exp, old_comp, new_comp);
1802 ✗ iteratorsRenamed := renameComponentInIterators(iterators, old_comp, new_comp);
1803 ✗ then
1804 Absyn.FOR_ITER_FARG(exp1_1, iterType, iteratorsRenamed);
1805 else
1806 algorithm
1807 ✗ print("-rename_component_in_function_args failed\n");
1808 ✗ then
1809 fail();
1810 end matchcontinue;
1811 end renameComponentInFunctionArgs;
1812
1813 protected function renameComponentInIterators
1814 "@author adrpo
1815 renames the components from expression present in iterators:
1816 i in exp1, j in exp2, etc"
1817 input Absyn.ForIterators iterators;
1818 input Absyn.ComponentRef oldComp;
1819 input Absyn.ComponentRef newComp;
1820 output Absyn.ForIterators iteratorsRenamed;
1821 algorithm
1822 ✗ iteratorsRenamed := list(match it
1823 local
1824 Absyn.Exp exp; String i;
1825 case Absyn.ITERATOR(i, NONE(), SOME(exp))
1826 algorithm
1827 ✗ exp := renameComponentInExp(exp, oldComp, newComp);
1828 ✗ then Absyn.ITERATOR(i, NONE(), SOME(exp));
1829 case Absyn.ITERATOR(i, NONE(), NONE())
1830 ✗ then Absyn.ITERATOR(i, NONE(), NONE());
1831 end match for it in iterators);
1832 end renameComponentInIterators;
1833
1834 protected function renameComponentInNamedArgs
1835 "author: x02lucpo
1836 helper function to renameComponentVisitor"
1837 input list<Absyn.NamedArg> inAbsynNamedArgLst1;
1838 input Absyn.ComponentRef inComponentRef2;
1839 input Absyn.ComponentRef inComponentRef3;
1840 output list<Absyn.NamedArg> outAbsynNamedArgLst;
1841 algorithm
1842 outAbsynNamedArgLst:=
1843 matchcontinue (inAbsynNamedArgLst1,inComponentRef2,inComponentRef3)
1844 local
1845 Absyn.Exp exp_1,exp;
1846 list<Absyn.NamedArg> res_1,res;
1847 String id;
1848 Absyn.ComponentRef old_comp,new_comp;
1849 case ({},_,_) then {}; /* the old name for the component */
1850 case ((Absyn.NAMEDARG(argName = id,argValue = exp) :: res),old_comp,new_comp)
1851 algorithm
1852 ✗ exp_1 := renameComponentInExp(exp, old_comp, new_comp);
1853 ✗ res_1 := renameComponentInNamedArgs(res, old_comp, new_comp);
1854 ✗ then
1855 (Absyn.NAMEDARG(id,exp_1) :: res_1);
1856 else
1857 algorithm
1858 ✗ print("-rename_component_in_namedArgs failed\n");
1859 ✗ then
1860 fail();
1861 end matchcontinue;
1862 end renameComponentInNamedArgs;
1863
1864 protected function renameComponentInExternalDecl
1865 "author: x02lucpo
1866 helper function to renameComponentVisitor"
1867 input Absyn.ExternalDecl external_;
1868 input Absyn.ComponentRef old_comp;
1869 input Absyn.ComponentRef new_comp;
1870 output Absyn.ExternalDecl external_1;
1871 algorithm
1872 ✗ print("-rename_component_in_external_decl not implemented yet\n");
1873 external_1 := external_;
1874 end renameComponentInExternalDecl;
1875
1876 protected function replaceStartInComponentRef
1877 "ie: (a.b.c.d, a.b, c.f) => c.f.c.d
1878 (a.b.c.d, d.c, c.f) => a.b.c.d
1879 WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
1880 WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
1881 (a.b.c.d, a.b, c.f.r) => a.b.c.d
1882 WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
1883 WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!"
1884 input Absyn.ComponentRef cr1;
1885 input Absyn.ComponentRef cr2;
1886 input Absyn.ComponentRef cr3;
1887 output Absyn.ComponentRef res;
1888 algorithm
1889 ✗ res := replaceStartInComponentRef2(cr1, cr2, cr3)
1890 "Dump.print_component_ref_str(cr1) => cref_str_tmp &
1891 print \" \" & print cref_str_tmp &
1892 Dump.print_component_ref_str(cr2) => cref_str_tmp &
1893 print \" \" & print cref_str_tmp &
1894 Dump.print_component_ref_str(cr3) => cref_str_tmp &
1895 print \" \" & print cref_str_tmp &
1896 Dump.print_component_ref_str(res) => cref_str_tmp &
1897 print \" res \" & print cref_str_tmp & print \"\\n\"" ;
1898 end replaceStartInComponentRef;
1899
1900 protected function replaceStartInComponentRef2
1901 "ie: (a.b.c.d, a.b, c.f) => c.f.c.d
1902 (a.b.c.d, d.c, c.f) => a.b.c.d
1903 WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
1904 WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
1905 (a.b.c.d, a.b, c.f.r) => a.b.c.d
1906 WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
1907 WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!"
1908 input Absyn.ComponentRef inComponentRef1;
1909 input Absyn.ComponentRef inComponentRef2;
1910 input Absyn.ComponentRef inComponentRef3;
1911 output Absyn.ComponentRef outComponentRef;
1912 algorithm
1913 outComponentRef:=
1914 matchcontinue (inComponentRef1,inComponentRef2,inComponentRef3)
1915 local
1916 String id,id2,id3;
1917 Absyn.ComponentRef res,cr1,cr,cr2,cr3;
1918 list<Absyn.Subscript> a;
1919 case (Absyn.CREF_IDENT(name = id),Absyn.CREF_IDENT(name = id2),(res as Absyn.CREF_IDENT()))
1920 algorithm
1921 ✗ true := stringEq(id, id2);
1922 then
1923 res;
1924 case (Absyn.CREF_QUAL(name = id,subscripts = a,componentRef = cr1),Absyn.CREF_IDENT(name = id2),Absyn.CREF_IDENT(name = id3))
1925 algorithm
1926 ✗ true := stringEq(id, id2);
1927 ✗ then
1928 Absyn.CREF_QUAL(id3,a,cr1);
1929 case (Absyn.CREF_QUAL(name = id,subscripts = a,componentRef = cr1),Absyn.CREF_QUAL(name = id2,componentRef = cr2),Absyn.CREF_QUAL(name = id3,componentRef = cr3))
1930 algorithm
1931 ✗ true := stringEq(id, id2);
1932 ✗ cr := replaceStartInComponentRef2(cr1, cr2, cr3);
1933 ✗ then
1934 Absyn.CREF_QUAL(id3,a,cr);
1935 else inComponentRef1;
1936 end matchcontinue;
1937 end replaceStartInComponentRef2;
1938
1939 protected function getComponentreplacementsrules
1940 "author: x02lucpo
1941 this extracts all the componentreplacementrules by
1942 searching for new rules until the list-size does not
1943 grow any more"
1944 input InteractiveTypes.Components inComponents;
1945 input InteractiveTypes.ComponentReplacementRules inComponentReplacementRules;
1946 input Integer inInteger;
1947 output InteractiveTypes.ComponentReplacementRules outComponentReplacementRules;
1948 algorithm
1949 outComponentReplacementRules := matchcontinue (inComponents,inComponentReplacementRules,inInteger)
1950 local
1951 Integer len,old_len;
1952 InteractiveTypes.Components comps;
1953 InteractiveTypes.ComponentReplacementRules comp_reps,comp_reps_1,comp_reps_2,comp_reps_res;
1954 case (_,comp_reps,old_len)
1955 algorithm
1956 ✗ len := lengthComponentReplacementRules(comp_reps);
1957 ✗ true := len == old_len;
1958 then
1959 comp_reps;
1960 case (comps,comp_reps,_)
1961 algorithm
1962 ✗ old_len := lengthComponentReplacementRules(comp_reps);
1963 ✗ comp_reps_1 := getNewComponentreplacementsrulesForEachRule(comps, comp_reps);
1964 ✗ comp_reps_2 := joinComponentReplacementRules(comp_reps_1, comp_reps);
1965 ✗ comp_reps_res := getComponentreplacementsrules(comps, comp_reps_2, old_len);
1966 then
1967 comp_reps_res;
1968 else
1969 algorithm
1970 ✗ print("-get_componentreplacementsrules failed\n");
1971 ✗ then
1972 fail();
1973 end matchcontinue;
1974 end getComponentreplacementsrules;
1975
1976 protected function getNewComponentreplacementsrulesForEachRule
1977 "author: x02lucpo
1978 extracts the replacement rules from the components:
1979 {COMP(path_1,path_2,cr1),COMP(path_3,path_2,cr2)},{REP_RULE(path_2,cr_1a,cr_1b)}
1980 => {REP_RULE(path_1,cr1.cr_1a,cr1.cr_1b),REP_RULE(path_3,cr2.cr_1a,cr2.cr_1b)}"
1981 input InteractiveTypes.Components inComponents;
1982 input InteractiveTypes.ComponentReplacementRules inComponentReplacementRules;
1983 output InteractiveTypes.ComponentReplacementRules outComponentReplacementRules;
1984 algorithm
1985 outComponentReplacementRules:=
1986 matchcontinue (inComponents,inComponentReplacementRules)
1987 local
1988 InteractiveTypes.Components comps,comps_1;
1989 InteractiveTypes.ComponentReplacementRules comp_reps,comp_reps_1,res,comp_reps_2,comp_reps_3;
1990 Absyn.Path path;
1991 Absyn.ComponentRef cr1,cr2;
1992 case (_,comp_reps)
1993 algorithm
1994 ✗ true := emptyComponentReplacementRules(comp_reps);
1995 then
1996 comp_reps;
1997 case (comps,comp_reps)
1998 algorithm
1999 ✗ InteractiveTypes.COMPONENTREPLACEMENT(path,cr1,cr2) := firstComponentReplacement(comp_reps);
2000 ✗ comps_1 := getComponentsWithType(comps, path);
2001 ✗ comp_reps_1 := makeComponentsReplacementRulesFromComponents(comps_1, cr1, cr2);
2002 ✗ res := restComponentReplacementRules(comp_reps);
2003 ✗ comp_reps_2 := getNewComponentreplacementsrulesForEachRule(comps, res);
2004 ✗ comp_reps_3 := joinComponentReplacementRules(comp_reps_1, comp_reps_2);
2005 then
2006 comp_reps_3;
2007 else
2008 algorithm
2009 ✗ print(
2010 "-get_new_componentreplacementsrules_for_each_rule failed\n");
2011 ✗ then
2012 fail();
2013 end matchcontinue;
2014 end getNewComponentreplacementsrulesForEachRule;
2015
2016 protected function makeComponentsReplacementRulesFromComponents
2017 "author: x02lucpo
2018
2019 this makes the replacementrules from each component in the first parameter:
2020 {COMP(path_1,path_2,cr1),COMP(path_3,path_2,cr2)},cr_1a,cr_1b
2021 => {REP_RULE(path_1,cr1.cr_1a,cr1.cr_1b),REP_RULE(path_3,cr2.cr_1a,cr2.cr_1b)}"
2022 input InteractiveTypes.Components inComponents1;
2023 input Absyn.ComponentRef inComponentRef2;
2024 input Absyn.ComponentRef inComponentRef3;
2025 output InteractiveTypes.ComponentReplacementRules outComponentReplacementRules;
2026 algorithm
2027 outComponentReplacementRules:=
2028 matchcontinue (inComponents1,inComponentRef2,inComponentRef3)
2029 local
2030 InteractiveTypes.Components comps,res;
2031 Absyn.ComponentRef cr_from,cr_to,cr,cr_from_1,cr_to_1;
2032 Absyn.Path path_class;
2033 InteractiveTypes.ComponentReplacement comp_rep;
2034 InteractiveTypes.ComponentReplacementRules comps_1,comp_reps_res;
2035 case (comps,_,_)
2036 algorithm
2037 ✗ true := emptyComponents(comps);
2038 then
2039 InteractiveTypes.COMPONENTREPLACEMENTRULES({},0);
2040 case (comps,cr_from,cr_to)
2041 algorithm
2042 ✗ InteractiveTypes.COMPONENTITEM(path_class,_,cr) := firstComponent(comps);
2043 ✗ cr_from_1 := AbsynUtil.joinCrefs(cr, cr_from);
2044 ✗ cr_to_1 := AbsynUtil.joinCrefs(cr, cr_to);
2045 ✗ comp_rep := InteractiveTypes.COMPONENTREPLACEMENT(path_class,cr_from_1,cr_to_1);
2046 ✗ res := restComponents(comps);
2047 ✗ comps_1 := makeComponentsReplacementRulesFromComponents(res, cr_from, cr_to);
2048 ✗ comp_reps_res := joinComponentReplacementRules(comps_1, InteractiveTypes.COMPONENTREPLACEMENTRULES({comp_rep},1));
2049 then
2050 comp_reps_res;
2051 case (comps,cr_from,cr_to)
2052 algorithm
2053 ✗ InteractiveTypes.EXTENDSITEM(path_class,_) := firstComponent(comps);
2054 ✗ comp_rep := InteractiveTypes.COMPONENTREPLACEMENT(path_class,cr_from,cr_to);
2055 ✗ res := restComponents(comps);
2056 ✗ comps_1 := makeComponentsReplacementRulesFromComponents(res, cr_from, cr_to);
2057 ✗ comp_reps_res := joinComponentReplacementRules(comps_1, InteractiveTypes.COMPONENTREPLACEMENTRULES({comp_rep},1));
2058 then
2059 comp_reps_res;
2060 else
2061 algorithm
2062 ✗ print("-make_componentsReplacementRules_from_components failed\n");
2063 ✗ then
2064 fail();
2065 end matchcontinue;
2066 end makeComponentsReplacementRulesFromComponents;
2067
2068 protected function emptyComponentReplacementRules
2069 "author: x02lucpo
2070 returns true if the componentReplacementRules are empty"
2071 input InteractiveTypes.ComponentReplacementRules inComponentReplacementRules;
2072 output Boolean outBoolean;
2073 algorithm
2074 outBoolean:=
2075 match inComponentReplacementRules
2076 case InteractiveTypes.COMPONENTREPLACEMENTRULES(componentReplacementLst = {}) then true;
2077 else false;
2078 end match;
2079 end emptyComponentReplacementRules;
2080
2081 protected function joinComponentReplacementRules
2082 " author: x02lucpo
2083 joins two componentReplacementRules lists by union"
2084 input InteractiveTypes.ComponentReplacementRules inComponentReplacementRules1;
2085 input InteractiveTypes.ComponentReplacementRules inComponentReplacementRules2;
2086 output InteractiveTypes.ComponentReplacementRules outComponentReplacementRules;
2087 algorithm
2088 outComponentReplacementRules:=
2089 match (inComponentReplacementRules1,inComponentReplacementRules2)
2090 local
2091 list<InteractiveTypes.ComponentReplacement> comps,comps1,comps2;
2092 Integer len;
2093 case (InteractiveTypes.COMPONENTREPLACEMENTRULES(componentReplacementLst = comps1),InteractiveTypes.COMPONENTREPLACEMENTRULES(componentReplacementLst = comps2))
2094 algorithm
2095 ✗ comps := List.union(comps1, comps2);
2096 ✗ len := listLength(comps);
2097 ✗ then
2098 InteractiveTypes.COMPONENTREPLACEMENTRULES(comps,len);
2099 end match;
2100 end joinComponentReplacementRules;
2101
2102 protected function lengthComponentReplacementRules
2103 "author: x02lucpo
2104 return the number of the componentReplacementRules"
2105 input InteractiveTypes.ComponentReplacementRules inComponentReplacementRules;
2106 output Integer outInteger;
2107 algorithm
2108 outInteger:=
2109 match inComponentReplacementRules
2110 local Integer len;
2111 case InteractiveTypes.COMPONENTREPLACEMENTRULES(the = len) then len;
2112 end match;
2113 end lengthComponentReplacementRules;
2114
2115 protected function firstComponentReplacement
2116 "author: x02lucpo
2117 extract the first componentReplacement in
2118 the componentReplacementReplacementRules"
2119 input InteractiveTypes.ComponentReplacementRules inComponentReplacementRules;
2120 output InteractiveTypes.ComponentReplacement outComponentReplacement;
2121 algorithm
2122 outComponentReplacement:=
2123 match inComponentReplacementRules
2124 local
2125 InteractiveTypes.ComponentReplacement comp;
2126 case InteractiveTypes.COMPONENTREPLACEMENTRULES(componentReplacementLst = {})
2127 algorithm
2128 ✗ print("-first_componentReplacement failed: no componentReplacementReplacementRules\n");
2129 ✗ then
2130 fail();
2131 case InteractiveTypes.COMPONENTREPLACEMENTRULES(componentReplacementLst = (comp :: _)) then comp;
2132 end match;
2133 end firstComponentReplacement;
2134
2135 protected function restComponentReplacementRules
2136 "author: x02lucpo
2137 extract the rest componentReplacementRules from the components"
2138 input InteractiveTypes.ComponentReplacementRules inComponentReplacementRules;
2139 output InteractiveTypes.ComponentReplacementRules outComponentReplacementRules;
2140 algorithm
2141 outComponentReplacementRules:=
2142 match inComponentReplacementRules
2143 local
2144 Integer len_1,len;
2145 list<InteractiveTypes.ComponentReplacement> res;
2146 case InteractiveTypes.COMPONENTREPLACEMENTRULES(componentReplacementLst = {}) then InteractiveTypes.COMPONENTREPLACEMENTRULES({},0);
2147 case InteractiveTypes.COMPONENTREPLACEMENTRULES(componentReplacementLst = (_ :: res),the = len)
2148 algorithm
2149 ✗ len_1 := len - 1;
2150 ✗ then
2151 InteractiveTypes.COMPONENTREPLACEMENTRULES(res,len_1);
2152 end match;
2153 end restComponentReplacementRules;
2154
2155 protected function getComponentsWithType
2156 "extracts all the components that have the type"
2157 input InteractiveTypes.Components inComponents;
2158 input Absyn.Path inPath;
2159 output InteractiveTypes.Components outComponents;
2160 protected
2161 list<InteractiveTypes.Component> comps;
2162 algorithm
2163 ✗ comps := list(comp for comp guard AbsynUtil.pathEqual(inPath, componentTypePath(comp)) in inComponents.componentLst);
2164 ✗ outComponents := InteractiveTypes.COMPONENTS(comps, listLength(comps));
2165 end getComponentsWithType;
2166
2167 protected function extractAllComponents
2168 "author: x02lucpo
2169 this traverse all the classes and
2170 extracts all the components and \"extends\""
2171 input Absyn.Program p;
2172 input Absyn.Path path;
2173 output InteractiveTypes.Components comps;
2174 algorithm
2175 comps := match path
2176 local
2177 SCode.Program p_1;
2178 FCore.Graph env;
2179
2180 // if we have a qualified class, a modification into it can affect any other
2181 case _
2182 algorithm
2183 ✗ p_1 := AbsynToSCode.translateAbsyn2SCode(p);
2184 ✗ (_,env) := Inst.makeEnvFromProgram(p_1);
2185 ✗ (_,_,(comps,_,_)) := AbsynUtil.traverseClasses(p, NONE(), extractAllComponentsVisitor,(InteractiveTypes.COMPONENTS({},0),p,env), true) "traverse protected";
2186 then
2187 comps;
2188 end match;
2189 end extractAllComponents;
2190
2191 protected function extractAllComponentsVisitor
2192 "author: x02lucpo
2193 the visitor for traverse-classes that extracts all
2194 the components and extends from all classes"
2195 input tuple<Absyn.Class, Option<Absyn.Path>, tuple<InteractiveTypes.Components, Absyn.Program, FCore.Graph>> inTplAbsynClassAbsynPathOptionTplComponentsAbsynProgramEnvEnv;
2196 output tuple<Absyn.Class, Option<Absyn.Path>, tuple<InteractiveTypes.Components, Absyn.Program, FCore.Graph>> outTplAbsynClassAbsynPathOptionTplComponentsAbsynProgramEnvEnv;
2197 algorithm
2198 outTplAbsynClassAbsynPathOptionTplComponentsAbsynProgramEnvEnv:=
2199 matchcontinue inTplAbsynClassAbsynPathOptionTplComponentsAbsynProgramEnvEnv
2200 local
2201 Absyn.Path path_1,pa_1,pa;
2202 Option<Absyn.Path> paOpt;
2203 FCore.Graph cenv,env;
2204 InteractiveTypes.Components comps_1,comps;
2205 Absyn.Class class_;
2206 String id;
2207 SourceInfo file_info;
2208 Absyn.Program p;
2209 case ((class_ as Absyn.CLASS(name = id,info = file_info)),SOME(pa),(comps,p,env))
2210 algorithm
2211 ✗ false := isReadOnly(file_info);
2212 ✗ path_1 := AbsynUtil.joinPaths(pa, Absyn.IDENT(id));
2213 ✗ cenv := getClassEnvNoElaboration(p, path_1, env);
2214 ✗ (_,pa_1) := Inst.makeFullyQualified(FCore.emptyCache(), cenv, path_1);
2215 ✗ comps_1 := extractComponentsFromClass(class_, pa_1, comps, cenv);
2216 ✗ then
2217 ((class_,SOME(pa),(comps_1,p,env)));
2218 case ((class_ as Absyn.CLASS(name = id,info = file_info)),NONE(),(comps,p,env))
2219 algorithm
2220 ✗ false := isReadOnly(file_info);
2221 ✗ path_1 := Absyn.IDENT(id);
2222
2223 ✗ cenv := getClassEnvNoElaboration(p, path_1, env);
2224 ✗ (_,pa_1) := Inst.makeFullyQualified(FCore.emptyCache(),cenv, path_1);
2225 ✗ comps_1 := extractComponentsFromClass(class_, pa_1, comps, cenv);
2226 ✗ then
2227 ((class_,NONE(),(comps_1,p,env)));
2228 ✗ case (class_ ,paOpt,(comps,p,env)) then ((class_,paOpt,(comps,p,env)));
2229 end matchcontinue;
2230 end extractAllComponentsVisitor;
2231
2232 protected function isReadOnly
2233 input SourceInfo file_info;
2234 output Boolean res;
2235 algorithm
2236 res := match file_info
2237 case SOURCEINFO(isReadOnly = res) then res;
2238 end match;
2239 end isReadOnly;
2240
2241 protected function extractComponentsFromClass
2242 "author: x02lucpo
2243 help function to extractAllComponentsVisitor"
2244 input Absyn.Class inClass;
2245 input Absyn.Path inPath;
2246 input InteractiveTypes.Components inComponents;
2247 input FCore.Graph inEnv;
2248 output InteractiveTypes.Components outComponents;
2249 algorithm
2250 outComponents:=
2251 match (inClass,inPath,inComponents,inEnv)
2252 local
2253 InteractiveTypes.Components comps_1,comps;
2254 Absyn.ClassDef classdef;
2255 Absyn.Path pa;
2256 FCore.Graph env;
2257 case (Absyn.CLASS(body = classdef),pa,comps,env) /* the QUALIFIED path */
2258 algorithm
2259 ✗ comps_1 := extractComponentsFromClassdef(pa, classdef, comps, env);
2260 then
2261 comps_1;
2262 else
2263 algorithm
2264 ✗ print("-extract_components_from_class failed\n");
2265 ✗ then
2266 fail();
2267 end match;
2268 end extractComponentsFromClass;
2269
2270 protected function extractComponentsFromClassdef
2271 "author: x02lucpo
2272 help function to extractAllComponentsVisitor"
2273 input Absyn.Path inPath;
2274 input Absyn.ClassDef inClassDef;
2275 input InteractiveTypes.Components inComponents;
2276 input FCore.Graph inEnv;
2277 output InteractiveTypes.Components outComponents;
2278 algorithm
2279 outComponents:= matchcontinue (inPath,inClassDef,inComponents,inEnv)
2280 local
2281 InteractiveTypes.Components comps_1,comps;
2282 Absyn.Path pa;
2283 list<Absyn.ClassPart> parts;
2284 FCore.Graph env;
2285 list<Absyn.ElementArg> elementargs;
2286 case (pa,Absyn.PARTS(classParts = parts),comps,env) /* the QUALIFIED path for the class */
2287 algorithm
2288 ✗ comps_1 := extractComponentsFromClassparts(pa, parts, comps, env);
2289 then
2290 comps_1;
2291 case (pa,Absyn.DERIVED(typeSpec=Absyn.TPATH(_,_),arguments = elementargs),comps,env)
2292 algorithm
2293 ✗ comps_1 := extractComponentsFromElementargs(pa, elementargs, comps, env)
2294 "& print \"extract_components_from_classdef for DERIVED not implemented yet\\n\"" ;
2295 then
2296 comps_1;
2297 case (pa,Absyn.CLASS_EXTENDS(parts = parts),comps,env)
2298 algorithm
2299 ✗ comps_1 := extractComponentsFromClassparts(pa, parts, comps, env);
2300 then
2301 comps_1;
2302 else inComponents;
2303 end matchcontinue;
2304 end extractComponentsFromClassdef;
2305
2306 protected function extractComponentsFromClassparts
2307 "author: x02lucpo
2308 help function to extractAllComponentsVisitor"
2309 input Absyn.Path inPath;
2310 input list<Absyn.ClassPart> inAbsynClassPartLst;
2311 input InteractiveTypes.Components inComponents;
2312 input FCore.Graph inEnv;
2313 output InteractiveTypes.Components outComponents;
2314 algorithm
2315 outComponents:= matchcontinue (inPath,inAbsynClassPartLst,inComponents,inEnv)
2316 local
2317 InteractiveTypes.Components comps,comps_1,comps_2;
2318 FCore.Graph env;
2319 Absyn.Path pa;
2320 list<Absyn.ElementItem> elements;
2321 list<Absyn.ClassPart> res;
2322
2323 case (_,{},comps,_) then comps; /* the QUALIFIED path for the class */
2324
2325 case (pa,(Absyn.PUBLIC(contents = elements) :: res),comps,env)
2326 algorithm
2327 ✗ comps_1 := extractComponentsFromClassparts(pa, res, comps, env);
2328 ✗ comps_2 := extractComponentsFromElements(pa, elements, comps_1, env);
2329 then
2330 comps_2;
2331
2332 case (pa,(Absyn.PROTECTED(contents = elements) :: res),comps,env)
2333 algorithm
2334 ✗ comps_1 := extractComponentsFromClassparts(pa, res, comps, env);
2335 ✗ comps_2 := extractComponentsFromElements(pa, elements, comps_1, env);
2336 then
2337 comps_2;
2338
2339 else inComponents;
2340
2341 end matchcontinue;
2342 end extractComponentsFromClassparts;
2343
2344 protected function extractComponentsFromElements
2345 "author: x02lucpo
2346 help function to extractAllComponentsVisitor"
2347 input Absyn.Path inPath;
2348 input list<Absyn.ElementItem> inAbsynElementItemLst;
2349 input InteractiveTypes.Components inComponents;
2350 input FCore.Graph inEnv;
2351 output InteractiveTypes.Components outComponents;
2352 algorithm
2353 outComponents:=
2354 matchcontinue (inPath,inAbsynElementItemLst,inComponents,inEnv)
2355 local
2356 InteractiveTypes.Components comps,comps_1,comps_2;
2357 FCore.Graph env;
2358 Absyn.Path pa;
2359 Absyn.ElementSpec elementspec;
2360 list<Absyn.ElementItem> res;
2361 Absyn.ElementItem element;
2362 case (_,{},comps,_) then comps; /* the QUALIFIED path for the class */
2363 case (pa,(Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = elementspec)) :: res),comps,env)
2364 algorithm
2365 ✗ comps_1 := extractComponentsFromElements(pa, res, comps, env);
2366 ✗ comps_2 := extractComponentsFromElementspec(pa, elementspec, comps_1, env);
2367 then
2368 comps_2;
2369 case (pa,(_ :: res),comps,env)
2370 algorithm
2371 ✗ comps := extractComponentsFromElements(pa, res, comps, env);
2372 then
2373 comps;
2374 end matchcontinue;
2375 end extractComponentsFromElements;
2376
2377 protected function extractComponentsFromElementspec
2378 "author: x02lucpo
2379 help function to extractAllComponentsVisitor"
2380 input Absyn.Path inPath;
2381 input Absyn.ElementSpec inElementSpec;
2382 input InteractiveTypes.Components inComponents;
2383 input FCore.Graph inEnv;
2384 output InteractiveTypes.Components outComponents;
2385 algorithm
2386 outComponents:=
2387 matchcontinue (inPath,inElementSpec,inComponents,inEnv)
2388 local
2389 String id;
2390 FCore.Graph cenv,env;
2391 Absyn.Path path_1,path,pa;
2392 InteractiveTypes.Components comps_1,comps,comps_2;
2393 list<Absyn.ComponentItem> comp_items;
2394 InteractiveTypes.Component comp;
2395 list<Absyn.ElementArg> elementargs;
2396 FCore.Cache cache;
2397
2398 case (pa,Absyn.COMPONENTS(typeSpec = Absyn.TPATH(path_1,_),components = comp_items),comps,env) /* the QUALIFIED path for the class */
2399 algorithm
2400 ✗ (cache,SCode.CLASS(name=id),cenv) := Lookup.lookupClass(FCore.emptyCache(),env, path_1);
2401 ✗ path_1 := Absyn.IDENT(id);
2402 ✗ (cache,path) := Inst.makeFullyQualified(cache, cenv, path_1);
2403 ✗ comps_1 := extractComponentsFromComponentitems(pa, path, comp_items, comps, env);
2404 then
2405 comps_1;
2406 case (pa,Absyn.EXTENDS(path = path_1,elementArg = elementargs),comps,env)
2407 algorithm
2408 ✗ (cache,_,cenv) := Lookup.lookupClass(FCore.emptyCache(),env, path_1)
2409 "print \"extract_components_from_elementspec Absyn.EXTENDS(path,_) not implemented yet\"" ;
2410 ✗ (_,path) := Inst.makeFullyQualified(cache,cenv, path_1);
2411 ✗ comp := InteractiveTypes.EXTENDSITEM(pa,path);
2412 ✗ comps_1 := addComponentToComponents(comp, comps);
2413 ✗ comps_2 := extractComponentsFromElementargs(pa, elementargs, comps_1, env);
2414 then
2415 comps_2;
2416 else inComponents;
2417 /* rule extract_components_from_class(class,pa,comps,env) => comps\'
2418 -------------------------------
2419 extract_components_from_elementspec(pa,Absyn.CLASSDEF(_,class), comps,env) => comps\' */
2420 end matchcontinue;
2421 end extractComponentsFromElementspec;
2422
2423 protected function extractComponentsFromComponentitems
2424 "author: x02lucpo
2425 help function to extractAllComponentsVisitor"
2426 input Absyn.Path inPath1;
2427 input Absyn.Path inPath2;
2428 input list<Absyn.ComponentItem> inAbsynComponentItemLst3;
2429 input InteractiveTypes.Components inComponents4;
2430 input FCore.Graph inEnv5;
2431 output InteractiveTypes.Components outComponents;
2432 algorithm
2433 outComponents:=
2434 matchcontinue (inPath1,inPath2,inAbsynComponentItemLst3,inComponents4,inEnv5)
2435 local
2436 InteractiveTypes.Components comps,comps_1,comps_2,comps_3;
2437 FCore.Graph env;
2438 Absyn.ComponentRef comp;
2439 Absyn.Path pa,path;
2440 String id;
2441 Option<Absyn.Modification> mod_opt;
2442 list<Absyn.ComponentItem> res;
2443 case (_,_,{},comps,_) then comps; /* the QUALIFIED path for the class the fully qualifired path for the type of the component */
2444 case (pa,path,(Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = id,modification = mod_opt)) :: res),comps,env)
2445 algorithm
2446 ✗ comps_1 := extractComponentsFromComponentitems(pa, path, res, comps, env);
2447 ✗ comp := Absyn.CREF_IDENT(id,{});
2448 ✗ comps_2 := addComponentToComponents(InteractiveTypes.COMPONENTITEM(pa,path,comp), comps_1);
2449 ✗ comps_3 := extractComponentsFromModificationOption(pa, mod_opt, comps_2, env);
2450 then
2451 comps_3;
2452 else
2453 algorithm
2454 ✗ print("-extract_components_from_componentitems failed\n");
2455 ✗ then
2456 fail();
2457 end matchcontinue;
2458 end extractComponentsFromComponentitems;
2459
2460 protected function extractComponentsFromElementargs
2461 input Absyn.Path inPath;
2462 input list<Absyn.ElementArg> inAbsynElementArgLst;
2463 input InteractiveTypes.Components inComponents;
2464 input FCore.Graph inEnv;
2465 output InteractiveTypes.Components outComponents;
2466 algorithm
2467 outComponents:=
2468 matchcontinue (inPath,inAbsynElementArgLst,inComponents,inEnv)
2469 local
2470 Absyn.Path pa;
2471 InteractiveTypes.Components comps,comps_1,comps_2,comps_3;
2472 FCore.Graph env;
2473 Absyn.ElementSpec elementspec,elementspec2;
2474 list<Absyn.ElementArg> res;
2475 Option<Absyn.Modification> mod_opt;
2476 case (_,{},comps,_) then comps; /* the QUALIFIED path for the class */
2477 case (pa,(Absyn.REDECLARATION(elementSpec = elementspec,constrainClass = SOME(Absyn.CONSTRAINCLASS(elementspec2,_))) :: res),comps,env)
2478 algorithm
2479 ✗ comps_1 := extractComponentsFromElementspec(pa, elementspec, comps, env);
2480 ✗ comps_2 := extractComponentsFromElementspec(pa, elementspec2, comps_1, env);
2481 ✗ comps_3 := extractComponentsFromElementargs(pa, res, comps_2, env);
2482 then
2483 comps_3;
2484 case (pa,(Absyn.REDECLARATION(elementSpec = elementspec,constrainClass = SOME(_)) :: res),comps,env)
2485 algorithm
2486 ✗ comps_1 := extractComponentsFromElementspec(pa, elementspec, comps, env);
2487 ✗ comps_2 := extractComponentsFromElementargs(pa, res, comps_1, env);
2488 then
2489 comps_2;
2490 case (pa,(Absyn.MODIFICATION(modification = mod_opt) :: res),comps,env)
2491 algorithm
2492 ✗ comps_1 := extractComponentsFromModificationOption(pa, mod_opt, comps, env);
2493 ✗ comps_2 := extractComponentsFromElementargs(pa, res, comps_1, env);
2494 then
2495 comps_2;
2496 case (pa,(_ :: res),comps,env)
2497 algorithm
2498 ✗ comps_1 := extractComponentsFromElementargs(pa, res, comps, env);
2499 then
2500 comps_1;
2501 end matchcontinue;
2502 end extractComponentsFromElementargs;
2503
2504 protected function extractComponentsFromModificationOption
2505 input Absyn.Path inPath;
2506 input Option<Absyn.Modification> inAbsynModificationOption;
2507 input InteractiveTypes.Components inComponents;
2508 input FCore.Graph inEnv;
2509 output InteractiveTypes.Components outComponents;
2510 algorithm
2511 outComponents:=
2512 match (inPath,inAbsynModificationOption,inComponents,inEnv)
2513 local
2514 Absyn.Path pa;
2515 InteractiveTypes.Components comps,comps_1;
2516 FCore.Graph env;
2517 list<Absyn.ElementArg> elementargs;
2518 case (_,NONE(),comps,_) then comps; /* the QUALIFIED path for the class */
2519 case (pa,SOME(Absyn.CLASSMOD(elementargs,_)),comps,env)
2520 algorithm
2521 ✗ comps_1 := extractComponentsFromElementargs(pa, elementargs, comps, env);
2522 then
2523 comps_1;
2524 end match;
2525 end extractComponentsFromModificationOption;
2526
2527 protected function emptyComponents
2528 "author: x02lucpo
2529 returns true if the components are empty"
2530 input InteractiveTypes.Components inComponents;
2531 output Boolean outBoolean;
2532 algorithm
2533 outBoolean:=
2534 match inComponents
2535 case InteractiveTypes.COMPONENTS(componentLst = {}) then true;
2536 else false;
2537 end match;
2538 end emptyComponents;
2539
2540 protected function firstComponent
2541 "author: x02lucpo
2542 extract the first component in the components"
2543 input InteractiveTypes.Components inComponents;
2544 output InteractiveTypes.Component outComponent;
2545 algorithm
2546 outComponent:=
2547 match inComponents
2548 local
2549 InteractiveTypes.Component comp;
2550 case InteractiveTypes.COMPONENTS(componentLst = {})
2551 algorithm
2552 ✗ print("-first_component failed: no components\n");
2553 ✗ then
2554 fail();
2555 case InteractiveTypes.COMPONENTS(componentLst = (comp :: _)) then comp;
2556 end match;
2557 end firstComponent;
2558
2559 protected function restComponents
2560 "author: x02lucpo
2561 extract the rest components from the compoents"
2562 input InteractiveTypes.Components inComponents;
2563 output InteractiveTypes.Components outComponents;
2564 algorithm
2565 outComponents:=
2566 match inComponents
2567 local
2568 Integer len_1,len;
2569 list<InteractiveTypes.Component> res;
2570 case InteractiveTypes.COMPONENTS(componentLst = {}) then InteractiveTypes.COMPONENTS({},0);
2571 case InteractiveTypes.COMPONENTS(componentLst = (_ :: res),the = len)
2572 algorithm
2573 ✗ len_1 := len - 1;
2574 ✗ then
2575 InteractiveTypes.COMPONENTS(res,len_1);
2576 end match;
2577 end restComponents;
2578
2579 protected function addComponentToComponents
2580 "author: x02lucpo
2581 add a component to components"
2582 input InteractiveTypes.Component inComponent;
2583 input InteractiveTypes.Components inComponents;
2584 output InteractiveTypes.Components outComponents;
2585 algorithm
2586 outComponents:=
2587 match (inComponent,inComponents)
2588 local
2589 Integer len_1,len;
2590 InteractiveTypes.Component comp;
2591 list<InteractiveTypes.Component> comps;
2592 case (comp,InteractiveTypes.COMPONENTS(componentLst = comps,the = len))
2593 algorithm
2594 ✗ len_1 := len + 1;
2595 ✗ then
2596 InteractiveTypes.COMPONENTS((comp :: comps),len_1);
2597 end match;
2598 end addComponentToComponents;
2599
2600 function componentTypePath
2601 input InteractiveTypes.Component comp;
2602 output Absyn.Path path;
2603 algorithm
2604 path := match comp
2605 ✗ case InteractiveTypes.COMPONENTITEM() then comp.the2;
2606 ✗ case InteractiveTypes.EXTENDSITEM() then comp.the2;
2607 end match;
2608 end componentTypePath;
2609
2610 protected function isParameterElement
2611 " Returns true if Element is a component of
2612 variability parameter, false otherwise."
2613 input Absyn.Element inElement;
2614 output Boolean outBoolean;
2615 algorithm
2616 outBoolean:=
2617 match inElement
2618 case Absyn.ELEMENT(specification = Absyn.COMPONENTS(attributes = Absyn.ATTR(variability = Absyn.PARAM()))) then true;
2619 else false;
2620 end match;
2621 end isParameterElement;
2622
2623 public function getParameterNames
2624 "Retrieves the names of all parameters in the class"
2625 input Absyn.Path path;
2626 input Absyn.Program inProgram;
2627 output list<String> outList;
2628 algorithm
2629 outList:=
2630 matchcontinue inProgram
2631 local
2632 Absyn.Class cdef;
2633 list<Absyn.Element> comps;
2634 list<list<Absyn.ComponentItem>> compelts;
2635 list<Absyn.ComponentItem> compelts_1;
2636 list<String> names;
2637 Absyn.Program p;
2638 case p
2639 algorithm
2640 ✗ cdef := ProgramUtil.getPathedClassInProgram(path, p);
2641 ✗ comps := InteractiveUtil.getComponentsInClass(cdef);
2642 ✗ compelts := list(InteractiveUtil.getComponentitemsInElement(c) for c guard isParameterElement(c) in comps);
2643 ✗ compelts_1 := List.flatten(compelts);
2644 ✗ names := List.map(compelts_1, getComponentitemName);
2645 then
2646 names;
2647 else {};
2648 end matchcontinue;
2649 end getParameterNames;
2650
2651 public function getClassEnv
2652 "Retrieves the environment of the class, including the
2653 frame of the class itself by partially instantiating it.
2654 It uses a LRU cache as to remember and speed things up"
2655 input Absyn.Program p;
2656 input Absyn.Path p_class;
2657 output GraphicEnvCache env_2;
2658 protected
2659 Option<list<tuple<Absyn.Program, Absyn.Path, GraphicEnvCache>>> ocache;
2660 list<tuple<Absyn.Program, Absyn.Path, GraphicEnvCache>> cache;
2661 Absyn.Program po;
2662 Absyn.Path patho;
2663 GraphicEnvCache envo;
2664 Boolean invalidate = false;
2665 FCore.Cache fcache;
2666 FCore.Graph env;
2667 algorithm
2668
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 if Flags.isSet(Flags.NF_API) then
2669 40 env_2 := GRAPHIC_ENV_FULL_CACHE(p, p_class, FCore.emptyCache(), FGraph.empty());
2670 40 return;
2671 end if;
2672
2673 // see if we have it already
2674 ✗ ocache := getGlobalRoot(Global.interactiveCache);
2675 ✗ if isSome(ocache) then
2676 ✗ SOME(cache) := ocache;
2677 ✗ for x in cache loop
2678 ✗ (po, patho, envo) := x;
2679 // found the path
2680 ✗ if AbsynUtil.pathEqual(patho, p_class) then
2681 // make sure the program did not change
2682 ✗ if referenceEq(po, p) then
2683 //print("Got it from cache: " + AbsynUtil.pathString(patho) + "\n");
2684 env_2 := envo;
2685 ✗ return;
2686 else // program not the same, invalidate cache
2687 //print("Invalidating: " + AbsynUtil.pathString(patho) + "\n");
2688 invalidate := true;
2689 break;
2690 end if;
2691 end if;
2692 end for;
2693
2694 // remove the entry if the program is not the same!
2695 if invalidate then
2696 ✗ SOME(cache) := ocache;
2697 ✗ cache := List.deleteMemberOnTrue(p_class, cache, matchPath);
2698 ✗ setGlobalRoot(Global.interactiveCache, SOME(cache));
2699 end if;
2700
2701 end if;
2702
2703 ✗ (fcache, env) := getClassEnv_dispatch(p, p_class);
2704 ✗ env_2 := GRAPHIC_ENV_FULL_CACHE(p, p_class, fcache, env);
2705
2706
2707 // update cache
2708 ✗ ocache := getGlobalRoot(Global.interactiveCache);
2709 ✗ if isSome(ocache) then
2710 ✗ SOME(cache) := ocache;
2711 ✗ setGlobalRoot(Global.interactiveCache, SOME((p, p_class, env_2)::cache));
2712 else // is NONE, have our first one in
2713 ✗ setGlobalRoot(Global.interactiveCache, SOME((p, p_class, env_2)::{}));
2714 end if;
2715 end getClassEnv;
2716
2717 function matchPath
2718 input Absyn.Path p;
2719 input tuple<Absyn.Program, Absyn.Path, GraphicEnvCache> entry;
2720 output Boolean matches;
2721 protected
2722 Absyn.Path po;
2723 algorithm
2724 ✗ (_, po, _) := entry;
2725 ✗ matches := AbsynUtil.pathEqual(po, p);
2726 end matchPath;
2727
2728 protected function getClassEnv_dispatch
2729 " Retrieves the environment of the class,
2730 including the frame of the class itself
2731 by partially instantiating it."
2732 input Absyn.Program p;
2733 input Absyn.Path p_class;
2734 output FCore.Cache cache;
2735 output FCore.Graph env_2;
2736 protected
2737 list<SCode.Element> p_1;
2738 FCore.Graph env,env_1,env2;
2739 SCode.Element cl;
2740 String id;
2741 SCode.Encapsulated encflag;
2742 SCode.Restriction restr;
2743 ClassInf.State ci_state;
2744 algorithm
2745 ✗ p_1 := AbsynToSCode.translateAbsyn2SCode(p);
2746 ✗ (cache,env) := Inst.makeEnvFromProgram(p_1);
2747 ✗ (cache, cl, env_1) := Lookup.lookupClass(cache,env, p_class);
2748
2749 env_2 := matchcontinue cl
2750 local
2751
2752 // Special case for derived classes. When instantiating a derived class, the environment
2753 // of the derived class is returned, which can be a totally different scope.
2754 case SCode.CLASS(name=id,encapsulatedPrefix=encflag,restriction=restr,classDef=SCode.DERIVED(typeSpec=Absyn.TPATH(_,_)))
2755 ✗ then env_1;
2756
2757 case SCode.CLASS(name=id,encapsulatedPrefix=encflag,restriction=restr)
2758 algorithm
2759 ✗ env2 := FGraph.openScope(env_1, encflag, id, FGraph.restrictionToScopeType(restr));
2760 ✗ ci_state := ClassInfUtil.start(restr, FGraph.getGraphName(env2));
2761 ✗ (cache,env_2,_,_,_) :=
2762 Inst.partialInstClassIn(cache,env2,InnerOuter.emptyInstHierarchy,
2763 DAE.NOMOD(), DAE.NOPRE(), ci_state, cl, SCode.PUBLIC(), {}, 0);
2764 ✗ then env_2;
2765
2766 ✗ else FGraph.empty();
2767 end matchcontinue;
2768 end getClassEnv_dispatch;
2769
2770 uniontype ComponentProperties
2771 record PROPERTIES
2772 Boolean isFinal;
2773 Boolean isFlow;
2774 Boolean isStream;
2775 Boolean isProtected;
2776 Boolean isReplaceable;
2777 Absyn.Variability variability;
2778 Absyn.InnerOuter innerOuter;
2779 Absyn.Direction direction;
2780 end PROPERTIES;
2781 end ComponentProperties;
2782
2783 public function setComponentProperties
2784 input Absyn.Path classPath;
2785 input String component;
2786 input list<Boolean> prefixes; // final, flow, [stream], protected, replaceable
2787 input String variability;
2788 input Boolean innerPrefix;
2789 input Boolean outerPrefix;
2790 input String direction;
2791 input output Absyn.Program program;
2792 output Values.Value result;
2793 protected
2794 Boolean is_final, is_flow, is_stream, is_protected, is_replaceable;
2795 ComponentProperties props;
2796 algorithm
2797 try
2798
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 8 times.
12 if listLength(prefixes) == 5 then
2799
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4 times.
4 {is_final, is_flow, is_stream, is_protected, is_replaceable} := prefixes;
2800 // Creating a component that is both flow and stream will cause the Absyn
2801 // to SCode translation to fail, which breaks the scripting environment.
2802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 false := is_flow and is_stream;
2803 else
2804
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 8 times.
8 {is_final, is_flow, is_protected, is_replaceable} := prefixes;
2805 is_stream := false;
2806 end if;
2807
2808
10/10
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 8 times.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 8 times.
✓ Branch 10 taken 4 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 10 times.
44 props := ComponentProperties.PROPERTIES(
2809 is_final, is_flow, is_stream, is_protected, is_replaceable,
2810 setElementVariability(variability),
2811 setInnerOuterAttributes(innerPrefix, outerPrefix),
2812 setElementCausality(direction)
2813 );
2814
2815 12 program := transformPathedClassInProgram(classPath, program,
2816 function setComponentPropertiesInClass(component = component, properties = props));
2817 12 result := ValuesMake.makeBoolean(true);
2818 else
2819 ✗ result := ValuesMake.makeBoolean(false);
2820 end try;
2821 end setComponentProperties;
2822
2823 protected function setComponentPropertiesInClass
2824 input output Absyn.Class cls;
2825 input String component;
2826 input ComponentProperties properties;
2827 protected
2828 Absyn.ClassDef body;
2829 algorithm
2830 12 body := cls.body;
2831
2832 cls.body := match body
2833 case Absyn.ClassDef.PARTS()
2834 algorithm
2835 12 body.classParts := setComponentPropertiesInClassparts(body.classParts, component, properties);
2836 then
2837 body;
2838
2839 case Absyn.ClassDef.CLASS_EXTENDS()
2840 algorithm
2841 ✗ body.parts := setComponentPropertiesInClassparts(body.parts, component, properties);
2842 then
2843 body;
2844 end match;
2845 end setComponentPropertiesInClass;
2846
2847 protected function setComponentPropertiesInClassparts
2848 input list<Absyn.ClassPart> inParts;
2849 input String component;
2850 input ComponentProperties properties;
2851 output list<Absyn.ClassPart> outParts;
2852 algorithm
2853 outParts := matchcontinue inParts
2854 local
2855 list<Absyn.ElementItem> publst, protlst, elts;
2856 Absyn.Element elt;
2857 list<Absyn.ClassPart> parts, rest;
2858 Absyn.ClassPart part;
2859
2860 case {} then {};
2861 case parts guard properties.isProtected /* public moved to protected protected moved to public */
2862 algorithm
2863 6 publst := ProgramUtil.getPublicList(parts);
2864
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
6 Absyn.ELEMENTITEM(elt) := List.getMemberOnTrue(component, publst, AbsynUtil.isElementItemNamed);
2865 2 elt := setComponentPropertiesInElement(elt, component, properties);
2866 2 publst := deleteOrUpdateComponentFromElementitems(component, publst, NONE()); // TODO: Do not move the component...
2867 2 protlst := ProgramUtil.getProtectedList(parts);
2868 2 protlst := List.appendElt(Absyn.ELEMENTITEM(elt), protlst);
2869 2 parts := ProgramUtil.replaceProtectedList(parts, protlst);
2870 2 parts := ProgramUtil.replacePublicList(parts, publst);
2871 then
2872 parts;
2873
2874 case parts guard not properties.isProtected /* protected moved to public protected attr not changed. */
2875 algorithm
2876 14 protlst := ProgramUtil.getProtectedList(parts);
2877
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
14 Absyn.ELEMENTITEM(elt) := List.getMemberOnTrue(component, protlst, AbsynUtil.isElementItemNamed);
2878 2 elt := setComponentPropertiesInElement(elt, component, properties);
2879 2 protlst := deleteOrUpdateComponentFromElementitems(component, protlst, NONE()); // TODO: Do not move the component...
2880 2 publst := ProgramUtil.getPublicList(parts);
2881 2 publst := List.appendElt(Absyn.ELEMENTITEM(elt), publst);
2882 2 parts := ProgramUtil.replacePublicList(parts, publst);
2883 2 parts := ProgramUtil.replaceProtectedList(parts, protlst);
2884 then
2885 parts;
2886
2887 case Absyn.PUBLIC(contents = elts) :: rest /* protected attr not changed. protected attr not changed, 2. */
2888 algorithm
2889 8 rest := setComponentPropertiesInClassparts(rest, component, properties);
2890 8 elts := setComponentPropertiesInElementitems(elts, component, properties);
2891 8 then
2892 Absyn.PUBLIC(elts) :: rest;
2893
2894 case Absyn.PROTECTED(contents = elts) :: rest /* protected attr not changed, 2. */
2895 algorithm
2896 6 rest := setComponentPropertiesInClassparts(rest, component, properties);
2897 6 elts := setComponentPropertiesInElementitems(elts, component, properties);
2898 6 then
2899 Absyn.PROTECTED(elts) :: rest;
2900
2901 case part :: rest /* protected attr not changed, 3. */
2902 algorithm
2903 2 rest := setComponentPropertiesInClassparts(rest, component, properties);
2904 then
2905 part :: rest;
2906
2907 end matchcontinue;
2908 end setComponentPropertiesInClassparts;
2909
2910 protected function setComponentPropertiesInElementitems
2911 input output list<Absyn.ElementItem> items;
2912 input String component;
2913 input ComponentProperties properties;
2914 algorithm
2915 14 items := List.findAndMap(items, function AbsynUtil.isElementItemNamed(name = component),
2916 function setComponentPropertiesInElementItem(component = component, properties = properties));
2917 end setComponentPropertiesInElementitems;
2918
2919 protected function setComponentPropertiesInElementItem
2920 input output Absyn.ElementItem item;
2921 input String component;
2922 input ComponentProperties properties;
2923 algorithm
2924 () := match item
2925 case Absyn.ElementItem.ELEMENTITEM()
2926 algorithm
2927 8 item.element := setComponentPropertiesInElement(item.element, component, properties);
2928 then
2929 ();
2930 end match;
2931 end setComponentPropertiesInElementItem;
2932
2933 protected function setComponentPropertiesInElement
2934 input output Absyn.Element element;
2935 input String component;
2936 input ComponentProperties properties;
2937 protected
2938 Absyn.ElementSpec spec;
2939 algorithm
2940 () := match element
2941 case Absyn.Element.ELEMENT(specification = spec as Absyn.ElementSpec.COMPONENTS())
2942 algorithm
2943 12 element.finalPrefix := properties.isFinal;
2944 12 element.redeclareKeywords := setReplaceableKeywordAttributes(element.redeclareKeywords, properties.isReplaceable);
2945 12 element.innerOuter := properties.innerOuter;
2946 12 spec.attributes := setElementAttributes(spec.attributes, properties);
2947 12 element.specification := spec;
2948 then
2949 ();
2950 end match;
2951 end setComponentPropertiesInElement;
2952
2953 protected function setReplaceableKeywordAttributes
2954 "Sets The RedeclareKeywords of an Element given a boolean \'replaceable\'.
2955 inputs: (Absyn.RedeclareKeywords option,
2956 bool /* repl */)
2957 outputs: Absyn.RedeclareKeywords option ="
2958 input Option<Absyn.RedeclareKeywords> inAbsynRedeclareKeywordsOption;
2959 input Boolean inBoolean;
2960 output Option<Absyn.RedeclareKeywords> outAbsynRedeclareKeywordsOption;
2961 algorithm
2962 outAbsynRedeclareKeywordsOption:=
2963 match (inAbsynRedeclareKeywordsOption,inBoolean)
2964 case (NONE(),false) then NONE(); /* false */
2965 case (SOME(Absyn.REPLACEABLE()),false) then NONE();
2966 case (SOME(Absyn.REDECLARE_REPLACEABLE()),false) then SOME(Absyn.REDECLARE());
2967 case (SOME(Absyn.REDECLARE()),false) then SOME(Absyn.REDECLARE());
2968 case (NONE(),true) then SOME(Absyn.REPLACEABLE()); /* true */
2969 case (SOME(Absyn.REDECLARE()),true) then SOME(Absyn.REDECLARE_REPLACEABLE());
2970 case (SOME(Absyn.REPLACEABLE()),true) then SOME(Absyn.REPLACEABLE());
2971 case (SOME(Absyn.REDECLARE_REPLACEABLE()),true) then SOME(Absyn.REDECLARE_REPLACEABLE());
2972 end match;
2973 end setReplaceableKeywordAttributes;
2974
2975 protected function setInnerOuterAttributes
2976 input Boolean isInner;
2977 input Boolean isOuter;
2978 output Absyn.InnerOuter outInnerOuter;
2979 algorithm
2980 outInnerOuter := match (isInner, isOuter)
2981 case (false, false) then Absyn.NOT_INNER_OUTER();
2982 case (true , false) then Absyn.INNER();
2983 case (false, true) then Absyn.OUTER();
2984 else Absyn.INNER_OUTER();
2985 end match;
2986 end setInnerOuterAttributes;
2987
2988 protected function setElementVariability
2989 "Sets Variability according to string value."
2990 input String inString;
2991 output Absyn.Variability outVariability;
2992 algorithm
2993 outVariability := match inString
2994 case "" then Absyn.VAR();
2995 case "discrete" then Absyn.DISCRETE();
2996 case "parameter" then Absyn.PARAM();
2997 case "constant" then Absyn.CONST();
2998 end match;
2999 end setElementVariability;
3000
3001 protected function setElementCausality
3002 "Sets Direction (causality) according to string value."
3003 input String inString;
3004 output Absyn.Direction outDirection;
3005 algorithm
3006 outDirection := match inString
3007 case "" then Absyn.BIDIR();
3008 case "input" then Absyn.INPUT();
3009 case "output" then Absyn.OUTPUT();
3010 end match;
3011 end setElementCausality;
3012
3013 protected function setElementAttributes
3014 input output Absyn.ElementAttributes attributes;
3015 input ComponentProperties properties;
3016 algorithm
3017 12 attributes := Absyn.ElementAttributes.ATTR(
3018 properties.isFlow,
3019 properties.isStream,
3020 attributes.parallelism,
3021 properties.variability,
3022 properties.direction,
3023 attributes.isField,
3024 attributes.arrayDim
3025 );
3026 end setElementAttributes;
3027
3028 public function getCrefInfo
3029 " author: adrpo@ida
3030 date : 2005-11-03, changed 2006-02-05 to match new SOURCEINFO
3031 Retrieves the Info attribute of a Class.
3032 When parsing classes, the source:
3033 file name + isReadOnly + start lineno + start columnno + end lineno + end columnno is added to the Class
3034 definition and to all Elements, see SourceInfo. This function retrieves the
3035 Info contents."
3036 input Absyn.Path classPath;
3037 input Absyn.Program program;
3038 output Values.Value result;
3039 protected
3040 Absyn.Class cls;
3041 SourceInfo info;
3042 algorithm
3043 try
3044 7 cls := ProgramUtil.getPathedClassInProgram(classPath, program);
3045 7 info := cls.info;
3046
1/2
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
56 result := ValuesMake.makeArray({
3047 ValuesMake.makeCodeTypeNameStr(Testsuite.friendly(info.fileName)),
3048 ValuesMake.makeCodeTypeNameStr(if info.isReadOnly then "readonly" else "writable"),
3049 ValuesMake.makeInteger(info.lineNumberStart),
3050 ValuesMake.makeInteger(info.columnNumberStart),
3051 ValuesMake.makeInteger(info.lineNumberEnd),
3052 ValuesMake.makeInteger(info.columnNumberEnd)
3053 });
3054 else
3055 ✗ result := ValuesMake.makeBoolean(false);
3056 end try;
3057 end getCrefInfo;
3058
3059 protected function getImportString
3060 " author: adrpo@ida
3061 date : 2005-11-11
3062 helperfunction to getElementType "
3063 input Absyn.Import inImport;
3064 output String outString;
3065 algorithm
3066 outString:=
3067 match inImport
3068 local
3069 String path_str,str,id;
3070 Absyn.Path path;
3071 case Absyn.NAMED_IMPORT(name = id,path = path)
3072 algorithm
3073 ✗ path_str := AbsynUtil.pathString(path);
3074 ✗ str := stringAppendList({"kind=named, id=",id,", path=",path_str});
3075 then
3076 str;
3077 case Absyn.QUAL_IMPORT(path = path)
3078 algorithm
3079 ✗ path_str := AbsynUtil.pathString(path);
3080 ✗ str := stringAppendList({"kind=qualified, path=",path_str});
3081 then
3082 str;
3083 case Absyn.UNQUAL_IMPORT(path = path)
3084 algorithm
3085 1 path_str := AbsynUtil.pathString(path);
3086 1 str := stringAppendList({"kind=unqualified, path=",path_str});
3087 then
3088 str;
3089 end match;
3090 end getImportString;
3091
3092 protected function getElementType
3093 " author: adrpo@ida
3094 date : 2005-11-11
3095 helperfunction to getElementInfo"
3096 input Absyn.ElementSpec inElementSpec;
3097 input Absyn.Element inElement;
3098 output String outString;
3099 algorithm
3100 outString:=
3101 match inElementSpec
3102 local
3103 String path_str,str,import_str,typename,flowPrefixstr,streamPrefixstr,variability_str,dir_str,names_str;
3104 Absyn.Path path;
3105 Absyn.TypeSpec typeSpec;
3106 Absyn.Import import_;
3107 list<String> names;
3108 Absyn.ElementAttributes attr;
3109 list<Absyn.ComponentItem> lst;
3110 case Absyn.EXTENDS(path = path)
3111 algorithm
3112 1 path_str := AbsynUtil.pathString(path);
3113 1 str := stringAppendList({"elementtype=extends, path=",path_str});
3114 then
3115 str;
3116 case Absyn.IMPORT(import_ = import_)
3117 algorithm
3118 1 import_str := getImportString(import_);
3119 1 str := stringAppendList({"elementtype=import, ",import_str});
3120 then
3121 str;
3122 case Absyn.COMPONENTS(attributes = attr,typeSpec = typeSpec,components = lst)
3123 algorithm
3124 5 typename := Dump.unparseTypeSpec(typeSpec);
3125
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 {names} := InteractiveUtil.getComponentItemsNameAndComment(lst, inElement);
3126 5 flowPrefixstr := InteractiveUtil.attrFlowStr(attr);
3127 5 streamPrefixstr := InteractiveUtil.attrStreamStr(attr);
3128 5 variability_str := InteractiveUtil.attrVariabilityStr(attr);
3129 5 dir_str := InteractiveUtil.attrDirectionStr(attr);
3130 5 names_str := stringDelimitList(names, ", ");
3131 5 str := stringAppendList({"elementtype=component, typename=",typename,", names={", names_str,"}, flow=",flowPrefixstr,
3132 ", stream=",streamPrefixstr,", variability=\"",variability_str,"\", direction=\"", dir_str, "\""});
3133 then
3134 str;
3135 end match;
3136 end getElementType;
3137
3138 protected function getElementInfo
3139 " author: adrpo@ida
3140 date : 2005-11-11
3141 helperfunction to constructElementInfo & getElementsInfo"
3142 input Absyn.ElementItem inElementItem;
3143 output String outString;
3144 algorithm
3145 outString:=
3146 matchcontinue inElementItem
3147 local
3148 String finalPrefix,repl,inout_str,str_restriction,element_str,sline_str,scol_str,eline_str,ecol_str,readonly_str,str,id,file;
3149 Boolean r_1,f,isReadOnly;
3150 Option<Absyn.RedeclareKeywords> r;
3151 Absyn.InnerOuter inout;
3152 Absyn.Restriction restr;
3153 Integer sline,scol,eline,ecol;
3154 Absyn.ElementSpec elementSpec;
3155 SourceInfo info;
3156 Absyn.Element el;
3157
3158 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(finalPrefix = f,redeclareKeywords = r,innerOuter = inout,specification = Absyn.CLASSDEF(class_ = Absyn.CLASS(name = id,restriction = restr,info = SOURCEINFO(fileName = file,isReadOnly = isReadOnly,lineNumberStart = sline,columnNumberStart = scol,lineNumberEnd = eline,columnNumberEnd = ecol))))) /* ok, first see if is a classdef if is not a classdef, just follow the normal stuff */
3159 algorithm
3160
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 finalPrefix := boolString(f);
3161 6 r_1 := keywordReplaceable(r);
3162
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 repl := boolString(r_1);
3163 6 inout_str := InteractiveUtil.innerOuterStr(inout);
3164 6 str_restriction := AbsynUtil.restrString(restr) "compile the classdef string" ;
3165 6 element_str := stringAppendList(
3166 {"elementtype=classdef, classname=",id,
3167 ", classrestriction=",str_restriction});
3168 6 file := Testsuite.friendly(file);
3169 6 sline_str := intString(sline);
3170 6 scol_str := intString(scol);
3171 6 eline_str := intString(eline);
3172 6 ecol_str := intString(ecol);
3173
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 readonly_str := if isReadOnly then "readonly" else "writable";
3174 6 str := stringAppendList(
3175 {"elementfile=\"",file,"\", elementreadonly=\"",
3176 readonly_str,"\", elementStartLine=",sline_str,", elementStartColumn=",scol_str,
3177 ", elementEndLine=",eline_str,", elementEndColumn=",ecol_str,", final=",finalPrefix,
3178 ", replaceable=",repl,", inout=\"",inout_str,"\", ",element_str});
3179 then
3180 str;
3181 case Absyn.ELEMENTITEM(element = el as Absyn.ELEMENT(finalPrefix = f,redeclareKeywords = r,innerOuter = inout,specification = elementSpec,info = SOURCEINFO(fileName = file,isReadOnly = isReadOnly,lineNumberStart = sline,columnNumberStart = scol,lineNumberEnd = eline,columnNumberEnd = ecol))) /* if is not a classdef, just follow the normal stuff */
3182 algorithm
3183
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 finalPrefix := boolString(f);
3184 7 r_1 := keywordReplaceable(r);
3185
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 repl := boolString(r_1);
3186 7 inout_str := InteractiveUtil.innerOuterStr(inout);
3187 7 element_str := getElementType(elementSpec, el);
3188 7 sline_str := intString(sline);
3189 7 scol_str := intString(scol);
3190 7 eline_str := intString(eline);
3191 7 ecol_str := intString(ecol);
3192
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 readonly_str := if isReadOnly then "readonly" else "writable";
3193 7 file := Testsuite.friendly(file);
3194 7 str := stringAppendList(
3195 {"elementfile=\"",file,"\", elementreadonly=\"",
3196 readonly_str,"\", elementStartLine=",sline_str,", elementStartColumn=",scol_str,
3197 ", elementEndLine=",eline_str,", elementEndColumn=",ecol_str,", final=",finalPrefix,
3198 ", replaceable=",repl,", inout=\"",inout_str,"\", ",element_str});
3199 then
3200 str;
3201 case Absyn.LEXER_COMMENT() then "elementtype=comment";
3202 else "elementtype=annotation"; /* for annotations we don\'t care */
3203 end matchcontinue;
3204 end getElementInfo;
3205
3206 protected function constructElementsInfo
3207 " author: adrpo@ida
3208 date : 2005-11-11
3209 helperfunction to getElementsInfo
3210 inputs: (string /* \"public\" or \"protected\" */, Absyn.ElementItem list)
3211 outputs: string"
3212 input String visibility;
3213 input list<Absyn.ElementItem> elements;
3214 output String result;
3215 protected
3216 list<String> elements_strl = {};
3217 String element_str;
3218 algorithm
3219
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 12 times.
25 for e in elements loop
3220 13 element_str := getElementInfo(e);
3221 13 element_str := stringAppendList({"{ rec(elementvisibility=", visibility, ", ", element_str, ") }"});
3222 elements_strl := element_str :: elements_strl;
3223 end for;
3224
3225 12 elements_strl := Dangerous.listReverseInPlace(elements_strl);
3226 12 result := stringDelimitList(elements_strl, ",\n");
3227
3228
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if not listEmpty(elements) then
3229 6 result := result + "\n";
3230 end if;
3231 end constructElementsInfo;
3232
3233 protected function appendNonEmptyStrings
3234 " author: adrpo@ida
3235 date : 2005-11-11
3236 helper to get_elements_info
3237 input: \"\", \"\", \",\" => \"\"
3238 \"some\", \"\", \",\" => \"some\"
3239 \"some\", \"some\", \",\" => \"some, some\""
3240 input String str1;
3241 input String str2;
3242 input String delim;
3243 output String outString;
3244 algorithm
3245
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if stringEmpty(str1) then
3246 outString := str2;
3247 elseif stringEmpty(str2) then
3248 outString := str1;
3249 else
3250 ✗ outString := stringAppendList({str1, delim, str2});
3251 end if;
3252 end appendNonEmptyStrings;
3253
3254 public function getElementsInfo
3255 " author: adrpo@ida
3256 date : 2005-11-11, changed 2006-02-06 to mirror the new SOURCEINFO
3257 Retrieves the Info attribute of an element.
3258 When parsing elements of the class composition, the source:
3259 -> file name + readonly + start lineno + start columnno + end lineno + end columnno is added to the Element
3260 and to the Class definition, see SourceInfo.
3261 This function retrieves the Info contents of the elements of a class."
3262 input Absyn.Path classPath;
3263 input Absyn.Program program;
3264 output Values.Value result;
3265 protected
3266 String result_str, public_str, protected_str;
3267 Absyn.Class cls;
3268 list<Absyn.ClassPart> parts;
3269 algorithm
3270 try
3271 6 cls := ProgramUtil.getPathedClassInProgram(classPath, program);
3272 6 parts := AbsynUtil.getClassPartsInClass(cls);
3273 6 public_str := constructElementsInfo("public", ProgramUtil.getPublicList(parts));
3274 6 protected_str := constructElementsInfo("protected", ProgramUtil.getProtectedList(parts));
3275 6 result_str := appendNonEmptyStrings(public_str, protected_str, ", ");
3276 6 result_str := stringAppendList({"{ ", result_str, " }"});
3277 else
3278 result_str := "Error";
3279 end try;
3280
3281 // getElementsInfo uses a format that can't be represented as a Value, fake it with a CodeType.
3282 6 result := ValuesMake.makeCodeTypeNameStr(result_str);
3283 end getElementsInfo;
3284
3285 public function getSourceFile
3286 " author: PA
3287 Retrieves the Source file attribute of a Class.
3288 When parsing classes, the source file name is added to the Class
3289 definition and to all Elements, see Absyn. This function retrieves the
3290 source file of the Class.
3291 inputs: (Absyn.ComponentRef, /* class */
3292 Absyn.Program)
3293 outputs: string"
3294 input Absyn.Path p_class;
3295 input Absyn.Program inProgram;
3296 output String outString;
3297 algorithm
3298 outString:=
3299 matchcontinue inProgram
3300 local
3301 Absyn.Class cdef;
3302 String filename;
3303 Absyn.Program p;
3304 case p /* class */
3305 algorithm
3306 ✗ cdef := ProgramUtil.getPathedClassInProgram(p_class, p);
3307 ✗ filename := AbsynUtil.classFilename(cdef);
3308 then filename;
3309 else "";
3310 end matchcontinue;
3311 end getSourceFile;
3312
3313 public function setSourceFile
3314 " author: PA
3315 Sets the source file of a Class. Is for instance used
3316 when adding a new class to an aldready stored package.
3317 The class should then have the same file as the package.
3318 inputs: (Absyn.ComponentRef, /* class */
3319 string, /* filename */
3320 Absyn.Program)
3321 outputs: (string, Absyn.Program)"
3322 input Absyn.Path path;
3323 input String inString;
3324 input Absyn.Program inProgram;
3325 output Boolean success;
3326 output Absyn.Program outProgram;
3327 algorithm
3328 (success,outProgram):=
3329 matchcontinue (inString, inProgram)
3330 local
3331 Absyn.Class cdef,cdef_1;
3332 Absyn.Within within_;
3333 Absyn.Program newp,p;
3334 String filename;
3335
3336 case (filename, p as Absyn.PROGRAM())
3337 algorithm
3338 1 cdef := ProgramUtil.getPathedClassInProgram(path, p);
3339 1 within_ := ProgramUtil.buildWithin(path);
3340 1 cdef_1 := AbsynUtil.setClassFilename(cdef, filename);
3341 // relocating the class to another file is the whole point here, so the
3342 // replacement must be allowed to bring the new file name along
3343 1 newp := ProgramUtil.updateProgram(Absyn.PROGRAM({cdef_1},within_), p, allowFilenameChange = true);
3344 then
3345 (true,newp);
3346 else (false,inProgram);
3347 end matchcontinue;
3348 end setSourceFile;
3349
3350 public function removeExtendsModifiers
3351 "Removes the extends modifiers of a class."
3352 input Absyn.Path inClassPath;
3353 input Absyn.Path inBaseClassPath;
3354 input Absyn.Program inProgram;
3355 input Boolean keepRedeclares;
3356 output Absyn.Program outProgram;
3357 output Boolean outResult;
3358 algorithm
3359 (outProgram,outResult) := matchcontinue (inClassPath,inBaseClassPath,inProgram)
3360 local
3361 Absyn.Path p_class,inherit_class;
3362 Absyn.Within within_;
3363 Absyn.Class cdef,cdef_1;
3364 GraphicEnvCache env;
3365 Absyn.Program newp,p;
3366
3367 case (p_class,inherit_class,p as Absyn.PROGRAM())
3368 algorithm
3369 1 within_ := ProgramUtil.buildWithin(p_class);
3370 1 cdef := ProgramUtil.getPathedClassInProgram(p_class, p);
3371 1 env := getClassEnv(p, p_class);
3372 1 cdef_1 := removeExtendsModifiersInClass(cdef, inherit_class, env, keepRedeclares);
3373 1 newp := ProgramUtil.updateProgram(Absyn.PROGRAM({cdef_1},within_), p);
3374 then
3375 (newp, true);
3376 else (inProgram, false);
3377 end matchcontinue;
3378 end removeExtendsModifiers;
3379
3380 protected function removeExtendsModifiersInClass
3381 input Absyn.Class inClass;
3382 input Absyn.Path inPath;
3383 input GraphicEnvCache inEnv;
3384 input Boolean keepRedeclares = false;
3385 output Absyn.Class outClass;
3386 algorithm
3387 outClass:=
3388 match (inClass,inPath,inEnv)
3389 local
3390 list<Absyn.ClassPart> parts_1,parts;
3391 String bcname;
3392 Option<String> cmt;
3393 Absyn.Path inherit_name;
3394 GraphicEnvCache env;
3395 list<Absyn.ElementArg> modif;
3396 list<String> typeVars;
3397 list<Absyn.NamedArg> classAttrs;
3398 list<Absyn.Annotation> ann;
3399 /* a class with parts */
3400 case (outClass as Absyn.CLASS(
3401 body = Absyn.PARTS(typeVars = typeVars,classAttrs = classAttrs,classParts = parts,ann = ann,comment = cmt)),
3402 inherit_name, env)
3403 algorithm
3404 1 parts_1 := removeExtendsModifiersInClassparts(parts, inherit_name, env, keepRedeclares);
3405 2 outClass.body := Absyn.PARTS(typeVars,classAttrs,parts_1,ann,cmt);
3406 then outClass;
3407 /* adrpo: handle also model extends M end M; */
3408 case (outClass as Absyn.CLASS(
3409 body = Absyn.CLASS_EXTENDS(baseClassName=bcname,parts = parts,modifications=modif,ann=ann,comment = cmt)),
3410 inherit_name, env)
3411 algorithm
3412 ✗ parts_1 := removeExtendsModifiersInClassparts(parts, inherit_name, env, keepRedeclares);
3413 ✗ outClass.body := Absyn.CLASS_EXTENDS(bcname,modif,cmt,parts_1,ann);
3414 then outClass;
3415 end match;
3416 end removeExtendsModifiersInClass;
3417
3418 protected function removeExtendsModifiersInClassparts
3419 input list<Absyn.ClassPart> inAbsynClassPartLst;
3420 input Absyn.Path inPath;
3421 input GraphicEnvCache inEnv;
3422 input Boolean keepRedeclares;
3423 output list<Absyn.ClassPart> outAbsynClassPartLst;
3424 algorithm
3425 outAbsynClassPartLst:=
3426 matchcontinue (inAbsynClassPartLst, inPath, inEnv)
3427 local
3428 list<Absyn.ClassPart> res,rest;
3429 list<Absyn.ElementItem> elts_1,elts;
3430 Absyn.Path inherit;
3431 GraphicEnvCache env;
3432 Absyn.ClassPart elt;
3433
3434 case ({}, _, _) then {};
3435
3436 case ((Absyn.PUBLIC(contents = elts) :: rest), inherit, env)
3437 algorithm
3438 1 res := removeExtendsModifiersInClassparts(rest, inherit, env, keepRedeclares);
3439 1 elts_1 := removeExtendsModifiersInElementitems(elts, inherit, env, keepRedeclares);
3440 1 then
3441 (Absyn.PUBLIC(elts_1) :: res);
3442
3443 case ((Absyn.PROTECTED(contents = elts) :: rest), inherit, env)
3444 algorithm
3445 ✗ res := removeExtendsModifiersInClassparts(rest, inherit, env, keepRedeclares);
3446 ✗ elts_1 := removeExtendsModifiersInElementitems(elts, inherit, env, keepRedeclares);
3447 ✗ then
3448 (Absyn.PROTECTED(elts_1) :: res);
3449
3450 case ((elt :: rest), inherit, env)
3451 algorithm
3452 ✗ res := removeExtendsModifiersInClassparts(rest, inherit, env, keepRedeclares);
3453 then
3454 (elt :: res);
3455
3456 end matchcontinue;
3457 end removeExtendsModifiersInClassparts;
3458
3459 protected function removeExtendsModifiersInElementitems
3460 input list<Absyn.ElementItem> inAbsynElementItemLst;
3461 input Absyn.Path inPath;
3462 input GraphicEnvCache inEnv;
3463 input Boolean keepRedeclares;
3464 output list<Absyn.ElementItem> outAbsynElementItemLst;
3465 algorithm
3466 outAbsynElementItemLst:=
3467 matchcontinue (inAbsynElementItemLst, inPath, inEnv)
3468 local
3469 list<Absyn.ElementItem> res,rest;
3470 Absyn.Element elt_1,elt;
3471 Absyn.Path inherit;
3472 GraphicEnvCache env;
3473 Absyn.ElementItem elitem;
3474
3475 case ({}, _, _) then {};
3476
3477 case ((Absyn.ELEMENTITEM(element = elt) :: rest), inherit, env)
3478 algorithm
3479 1 res := removeExtendsModifiersInElementitems(rest, inherit, env, keepRedeclares);
3480 1 elt_1 := removeExtendsModifiersInElement(elt, inherit, env, keepRedeclares);
3481 1 then
3482 (Absyn.ELEMENTITEM(elt_1) :: res);
3483
3484 case ((elitem :: rest), inherit, env)
3485 algorithm
3486 ✗ res := removeExtendsModifiersInElementitems(rest, inherit, env, keepRedeclares);
3487 then
3488 (elitem :: res);
3489 end matchcontinue;
3490 end removeExtendsModifiersInElementitems;
3491
3492 protected function removeExtendsModifiersInElement
3493 input Absyn.Element inElement;
3494 input Absyn.Path inPath;
3495 input GraphicEnvCache inEnv;
3496 input Boolean keepRedeclares;
3497 output Absyn.Element outElement;
3498 algorithm
3499 outElement:=
3500 matchcontinue (inElement,inPath,inEnv)
3501 local
3502 Boolean f;
3503 Option<Absyn.RedeclareKeywords> r;
3504 Absyn.InnerOuter i;
3505 Absyn.Path path,inherit,path_1;
3506 list<Absyn.ElementArg> eargs;
3507 SourceInfo info;
3508 Option<Absyn.ConstrainClass> constr;
3509 GraphicEnvCache env;
3510 Option<Absyn.Annotation> annOpt;
3511
3512 case (Absyn.ELEMENT(finalPrefix = f,redeclareKeywords = r,innerOuter = i,
3513 specification = Absyn.EXTENDS(path = path,elementArg = eargs,annotationOpt=annOpt),info = info,constrainClass = constr),
3514 inherit,env)
3515 algorithm
3516 1 (_, path_1) := mkFullyQual(env, path);
3517
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 true := AbsynUtil.pathEqual(inherit, path_1);
3518
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 eargs := if not keepRedeclares then {} else list(e for e guard(match e case Absyn.REDECLARATION() then true; else false; end match) in eargs);
3519
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
2 then
3520 Absyn.ELEMENT(f,r,i,Absyn.EXTENDS(path,eargs,annOpt),info,constr);
3521 else inElement;
3522 end matchcontinue;
3523 end removeExtendsModifiersInElement;
3524
3525 public function mkFullyQual
3526 input GraphicEnvCache env;
3527 input Absyn.Path ipath;
3528 input Boolean failOnError = false;
3529 output FCore.Cache ocache;
3530 output Absyn.Path opath;
3531 protected
3532 Absyn.Path cpath;
3533 Absyn.Program program;
3534 algorithm
3535
1/2
✓ Branch 1 taken 7098 times.
✗ Branch 2 not taken.
7098 if Flags.isSet(Flags.NF_API) then
3536 7098 ocache := cacheFromGraphicEnvCache(env);
3537 7098 (program, cpath) := cacheProgramAndPath(env);
3538 7098 opath := NFApi.mkFullyQual(program, cpath, ipath, failOnError);
3539 else
3540 ✗ (ocache, opath) := Inst.makeFullyQualified(cacheFromGraphicEnvCache(env), envFromGraphicEnvCache(env), ipath);
3541 end if;
3542 end mkFullyQual;
3543
3544 public function getExtendsModifierValue
3545 " Return the submodifier value of an extends clause
3546 for instance,
3547 model test extends A(p1=3,p2(z=3));end test;
3548 getExtendsModifierValue(test,A,p1) => 3"
3549 input Absyn.Path classPath;
3550 input Absyn.Path extendsPath;
3551 input Absyn.Path modifierPath;
3552 input Absyn.Program program;
3553 output Values.Value result;
3554 protected
3555 list<Absyn.ElementArg> ext_mod;
3556 algorithm
3557 try
3558
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
12 SOME(Absyn.EXTENDS(elementArg = ext_mod)) :=
3559 InteractiveUtil.getPathedExtendsInProgram(classPath, extendsPath, program);
3560 12 result := ValuesMake.makeCodeTypeNameStr(Dump.printExpStr(getModificationValue(ext_mod, modifierPath)));
3561 else
3562 2 result := ValuesMake.makeCodeTypeNameStr("");
3563 end try;
3564 end getExtendsModifierValue;
3565
3566 public function isExtendsModifierFinal
3567 "Returns true if the given modifier on an extends clause is final, for instance:
3568 model test extends A(final p1 = 3); end test;
3569 isExtendsModifierFinal(test, A, p1) => true"
3570 input Absyn.Path classPath;
3571 input Absyn.Path extendsPath;
3572 input Absyn.Path modifierPath;
3573 input Absyn.Program program;
3574 output Values.Value result;
3575 protected
3576 list<Absyn.ElementArg> ext_mod;
3577 algorithm
3578 try
3579
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
4 SOME(Absyn.EXTENDS(elementArg = ext_mod)) :=
3580 InteractiveUtil.getPathedExtendsInProgram(classPath, extendsPath, program);
3581 4 result := ValuesMake.makeBoolean(isModifierfinal(ext_mod, modifierPath));
3582 else
3583 ✗ result := ValuesMake.makeBoolean(false);
3584 end try;
3585 end isExtendsModifierFinal;
3586
3587 public function isModifierfinal
3588 " Helper function to isExtendsModifierFinal."
3589 input list<Absyn.ElementArg> inAbsynElementArgLst;
3590 input Absyn.Path inPath;
3591 output Boolean outBoolean;
3592 algorithm
3593 outBoolean:=
3594 match (inAbsynElementArgLst,inPath)
3595 local
3596 Boolean f;
3597 Absyn.Path p1,p2;
3598 list<Absyn.ElementArg> rest,args;
3599 String name1,name2;
3600 case ((Absyn.MODIFICATION(finalPrefix = f,path = p1,modification = SOME(_)) :: _),p2) guard AbsynUtil.pathEqual(p1, p2)
3601 then
3602 f;
3603 case ((Absyn.MODIFICATION(path = Absyn.IDENT(name = name1),modification = SOME(Absyn.CLASSMOD(elementArgLst=args))) :: _),Absyn.QUALIFIED(name = name2,path = p2)) guard stringEq(name1, name2)
3604 algorithm
3605 ✗ f := isModifierfinal(args, p2);
3606 then
3607 f;
3608 case ((_ :: rest),_)
3609 algorithm
3610 4 f := isModifierfinal(rest, inPath);
3611 then
3612 f;
3613 else false;
3614 end match;
3615 end isModifierfinal;
3616
3617 function makeExtendsFullyQualified
3618 " Makes an EXTENDS ElementSpec having a
3619 fully qualified extends path."
3620 input Absyn.ElementSpec inElementSpec;
3621 input GraphicEnvCache inEnv;
3622 output Absyn.ElementSpec outElementSpec;
3623 algorithm
3624 outElementSpec:=
3625 match (inElementSpec,inEnv)
3626 local
3627 Absyn.Path path_1,path;
3628 list<Absyn.ElementArg> earg;
3629 GraphicEnvCache env;
3630 Option<Absyn.Annotation> annOpt;
3631
3632 case (Absyn.EXTENDS(path = path,elementArg = earg,annotationOpt=annOpt),env)
3633 algorithm
3634 27 (_, path_1) := mkFullyQual(env, path);
3635 27 then
3636 Absyn.EXTENDS(path_1,earg,annOpt);
3637 end match;
3638 end makeExtendsFullyQualified;
3639
3640 public function removeComponentModifiers
3641 "Removes all the modifiers of a component."
3642 input Absyn.Path path;
3643 input String inComponentName;
3644 input Absyn.Program inProgram;
3645 input Boolean keepRedeclares;
3646 output Absyn.Program outProgram;
3647 output Boolean outResult;
3648 protected
3649 Absyn.Within within_;
3650 Absyn.Class cls;
3651 algorithm
3652 try
3653 2 within_ := ProgramUtil.buildWithin(path);
3654 2 cls := ProgramUtil.getPathedClassInProgram(path, inProgram);
3655 2 cls := InteractiveUtil.clearComponentModifiersInClass(cls, inComponentName, keepRedeclares);
3656 2 outProgram := ProgramUtil.updateProgram(Absyn.PROGRAM({cls}, within_), inProgram);
3657 outResult := true;
3658 else
3659 outProgram := inProgram;
3660 outResult := false;
3661 end try;
3662 end removeComponentModifiers;
3663
3664 public function getComponentModifierValue
3665 input Absyn.ComponentRef classRef;
3666 input Absyn.ComponentRef varRef;
3667 input Absyn.ComponentRef subModRef;
3668 input Absyn.Program program;
3669 output String valueStr;
3670 protected
3671 Absyn.Path cls_path;
3672 String name;
3673 Absyn.Class cls;
3674 list<Absyn.ElementArg> args;
3675 algorithm
3676 try
3677 22 cls_path := AbsynUtil.crefToPath(classRef);
3678 22 name := AbsynUtil.crefIdent(varRef);
3679 22 cls := ProgramUtil.getPathedClassInProgram(cls_path, program);
3680
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 22 times.
22 Absyn.COMPONENTITEM(component = Absyn.COMPONENT(modification =
3681 SOME(Absyn.CLASSMOD(elementArgLst = args)))) := InteractiveUtil.getComponentInClass(cls, name);
3682 22 valueStr := Dump.printExpStr(getModificationValue(args, AbsynUtil.crefToPath(subModRef)));
3683 else
3684 valueStr := "";
3685 end try;
3686 end getComponentModifierValue;
3687
3688 public function getModificationValue
3689 "Looks up a modifier in a list of element args and returns its binding
3690 expression, or fails if no modifier is found."
3691 input list<Absyn.ElementArg> args;
3692 input Absyn.Path path;
3693 output Absyn.Exp value = Absyn.INTEGER(0);
3694 protected
3695 String name;
3696 list<Absyn.ElementArg> rest_args = args;
3697 Absyn.ElementArg arg;
3698 Boolean found = false;
3699 algorithm
3700
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 33 times.
111 while not found loop
3701
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 71 times.
78 arg :: rest_args := rest_args;
3702
3703 found := match arg
3704 case Absyn.MODIFICATION() guard AbsynUtil.pathEqual(arg.path, path)
3705 algorithm
3706
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 25 times.
27 SOME(Absyn.CLASSMOD(eqMod = Absyn.EQMOD(exp = value))) := arg.modification;
3707 then
3708 true;
3709
3710 case Absyn.MODIFICATION(path = Absyn.IDENT(name = name))
3711 guard name == AbsynUtil.pathFirstIdent(path)
3712 algorithm
3713
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 SOME(Absyn.CLASSMOD(elementArgLst = rest_args)) := arg.modification;
3714 9 value := getModificationValue(rest_args, AbsynUtil.pathRest(path));
3715 then
3716 true;
3717
3718 else false;
3719 end match;
3720 end while;
3721 end getModificationValue;
3722
3723 public function getComponentModifierValues
3724 input Absyn.ComponentRef inComponentRef1;
3725 input Absyn.ComponentRef inComponentRef2;
3726 input Absyn.ComponentRef inComponentRef3;
3727 input Absyn.Program inProgram4;
3728 output String outString;
3729 algorithm
3730 outString := matchcontinue (inComponentRef1,inComponentRef2,inComponentRef3,inProgram4)
3731 local
3732 Absyn.Path p_class;
3733 String name,res;
3734 Absyn.Class cdef;
3735 list<Absyn.Element> comps;
3736 list<list<Absyn.ComponentItem>> compelts;
3737 list<Absyn.ComponentItem> compelts_1;
3738 Absyn.Modification mod;
3739 Absyn.ComponentRef class_,ident,subident;
3740 Absyn.Program p;
3741 list<Absyn.ElementArg> elementArgLst;
3742
3743 case (class_,ident,subident,p)
3744 algorithm
3745 1 p_class := AbsynUtil.crefToPath(class_);
3746
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 Absyn.IDENT(name) := AbsynUtil.crefToPath(ident);
3747 1 cdef := ProgramUtil.getPathedClassInProgram(p_class, p);
3748 1 comps := InteractiveUtil.getComponentsInClass(cdef);
3749 1 compelts := List.map(comps, InteractiveUtil.getComponentitemsInElement);
3750 1 compelts_1 := List.flatten(compelts);
3751
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 time.
1 {Absyn.COMPONENTITEM(component=Absyn.COMPONENT(modification=SOME(Absyn.CLASSMOD(elementArgLst=elementArgLst))))} := List.select1(compelts_1, InteractiveUtil.componentitemNamed, name);
3752 1 mod := getModificationValues(elementArgLst, AbsynUtil.crefToPath(subident));
3753 1 res := Dump.unparseModificationStr(mod);
3754 then
3755 res;
3756 else "Error";
3757 end matchcontinue;
3758 end getComponentModifierValues;
3759
3760 protected function getModificationValues
3761 "Helper function to getComponentModifierValues
3762 Investigates modifications to find submodifier."
3763 input list<Absyn.ElementArg> inAbsynElementArgLst;
3764 input Absyn.Path inPath;
3765 output Absyn.Modification outModification;
3766 algorithm
3767 outModification:=
3768 match (inAbsynElementArgLst,inPath)
3769 local
3770 Absyn.Path p1,p2;
3771 Absyn.Modification mod,res;
3772 list<Absyn.ElementArg> rest,args;
3773 String name1,name2;
3774 case ((Absyn.MODIFICATION(path = p1,modification = SOME(mod)) :: _),p2) guard AbsynUtil.pathEqual(p1, p2)
3775 then
3776 mod;
3777 case ((Absyn.MODIFICATION(path = Absyn.IDENT(name = name1),modification = SOME(Absyn.CLASSMOD(elementArgLst=args))) :: _),Absyn.QUALIFIED(name = name2,path = p2))
3778 guard stringEq(name1, name2)
3779 algorithm
3780 ✗ res := getModificationValues(args, p2);
3781 then
3782 res;
3783 case ((_ :: rest),_)
3784 algorithm
3785 ✗ mod := getModificationValues(rest, inPath);
3786 then
3787 mod;
3788 end match;
3789 end getModificationValues;
3790
3791 public function getComponentModifierNames
3792 "Return the modifiernames of a component"
3793 input Absyn.Path path;
3794 input String inComponentName;
3795 input Absyn.Program inProgram3;
3796 output list<String> outList;
3797 algorithm
3798 outList:=
3799 matchcontinue inProgram3
3800 local
3801 Absyn.Class cdef;
3802 list<Absyn.Element> comps;
3803 list<list<Absyn.ComponentItem>> compelts;
3804 list<Absyn.ComponentItem> compelts_1;
3805 list<Absyn.ElementArg> mod;
3806 list<String> res;
3807 Absyn.Program p;
3808 case p
3809 algorithm
3810 13 cdef := ProgramUtil.getPathedClassInProgram(path, p);
3811 13 comps := InteractiveUtil.getComponentsInClass(cdef);
3812 13 compelts := List.map(comps, InteractiveUtil.getComponentitemsInElement);
3813 13 compelts_1 := List.flatten(compelts);
3814
6/8
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10 times.
13 {Absyn.COMPONENTITEM(Absyn.COMPONENT(_,_,SOME(Absyn.CLASSMOD(mod,_))),_,_)} := List.select1(compelts_1, InteractiveUtil.componentitemNamed, inComponentName);
3815 10 res := getModificationNames(mod);
3816 then
3817 res;
3818 else {};
3819 end matchcontinue;
3820 end getComponentModifierNames;
3821
3822 protected function getModificationNames
3823 "Helper function to getComponentModifierNames"
3824 input list<Absyn.ElementArg> inAbsynElementArgLst;
3825 output list<String> outStringLst;
3826 algorithm
3827 outStringLst:=
3828 matchcontinue inAbsynElementArgLst
3829 local
3830 list<String> names,names2,res;
3831 String name;
3832 list<Absyn.ElementArg> rest,args;
3833 Absyn.Path p;
3834 case {} then {};
3835 case Absyn.MODIFICATION(path = Absyn.IDENT(name = name),modification = NONE()) :: rest
3836 algorithm
3837 ✗ names := getModificationNames(rest);
3838 then
3839 (name :: names);
3840 case Absyn.MODIFICATION(path = p,modification = SOME(Absyn.CLASSMOD({},_))) :: rest
3841 algorithm
3842 20 name := AbsynUtil.pathString(p);
3843 20 names := getModificationNames(rest);
3844 then
3845 (name :: names);
3846 // modifier with submodifiers -and- binding, e.g. m(...)=2, add also m to list
3847 case Absyn.MODIFICATION(path = p,modification = SOME(Absyn.CLASSMOD(args,Absyn.EQMOD()))) :: rest
3848 algorithm
3849 ✗ name := AbsynUtil.pathString(p);
3850 ✗ names2 := list(stringAppend(stringAppend(name, "."), n) for n in getModificationNames(args));
3851 ✗ names := getModificationNames(rest);
3852 ✗ res := listAppend(names2, names);
3853 then
3854 name::res;
3855 // modifier with submodifiers, e.g. m(...)
3856 case Absyn.MODIFICATION(path = p,modification = SOME(Absyn.CLASSMOD(args,_))) :: rest
3857 algorithm
3858 1 name := AbsynUtil.pathString(p);
3859
4/4
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 time.
3 names2 := list(stringAppend(stringAppend(name, "."), n) for n in getModificationNames(args));
3860 1 names := getModificationNames(rest);
3861 1 res := listAppend(names2, names);
3862 then
3863 res;
3864 case _ :: rest
3865 algorithm
3866 1 names := getModificationNames(rest);
3867 then
3868 names;
3869 end matchcontinue;
3870 end getModificationNames;
3871
3872 public function getComponentBinding
3873 " Returns the value of a component in a class.
3874 For example, the component
3875 Real x=1;
3876 returns 1.
3877 This can be used for both parameters, constants and variables."
3878 input Absyn.Path path;
3879 input String parameterName;
3880 input Absyn.Program program;
3881 output String bindingStr;
3882 protected
3883 Absyn.Class cls;
3884 Absyn.ComponentItem component;
3885 algorithm
3886 try
3887 8 cls := ProgramUtil.getPathedClassInProgram(path, program);
3888 8 component := InteractiveUtil.getComponentInClass(cls, parameterName);
3889 7 bindingStr := Dump.printExpStr(InteractiveUtil.getVariableBindingInComponentitem(component));
3890 else
3891 bindingStr := "";
3892 end try;
3893 end getComponentBinding;
3894
3895 protected function getComponentitemName
3896 " Returns the name of a ComponentItem"
3897 input Absyn.ComponentItem inComponentItem;
3898 output Absyn.Ident outIdent;
3899 algorithm
3900 outIdent := match inComponentItem
3901 local String id;
3902 case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = id)) then id;
3903 end match;
3904 end getComponentitemName;
3905
3906 public function renameClass
3907 "This function renames a class (given as a qualified path name) to a
3908 new name -in the same scope-. All references to the class name in the
3909 program is updated to the new name. The function does not allow a
3910 renaming that will move the class to another package. To do this, the
3911 class must be copied."
3912 input Absyn.Path oldName;
3913 input Absyn.Path newName;
3914 input output Absyn.Program program;
3915 output Values.Value result;
3916 protected
3917 FCore.Graph env;
3918 Absyn.Path new_name;
3919 list<Absyn.Path> paths;
3920 algorithm
3921 ✗ if AbsynUtil.pathIsQual(newName) then
3922 ✗ result := ValuesMake.makeBoolean(false);
3923 end if;
3924
3925 ✗ if AbsynUtil.pathIsQual(oldName) then
3926 ✗ new_name := AbsynUtil.joinPaths(AbsynUtil.stripLast(oldName), newName);
3927 else
3928 new_name := newName;
3929 end if;
3930
3931 // For now, renaming a class clears all caches...
3932 // Substantial analysis required to find out what to keep in cache and what must be thrown out
3933 ✗ (_, env) := Inst.makeEnvFromProgram(SymbolTable.getSCode());
3934 ✗ (program, _, (_, _, _, paths, _)) :=
3935 AbsynUtil.traverseClasses(program, NONE(), renameClassVisitor, (oldName, new_name, program, {}, env), true);
3936 ✗ result := ValuesMake.makeCodeTypeNameArray(paths);
3937 end renameClass;
3938
3939 protected function renameClassVisitor
3940 " This visitor renames a class given a new name.
3941 It returns a list of strings of renamed classes.
3942 The 'traversal-tuple' is therefore
3943 tuple<oldname, newname, program, string list, env>."
3944 input output tuple<Absyn.Class, Option<Absyn.Path>, tuple<Absyn.Path, Absyn.Path, Absyn.Program, list<Absyn.Path>, FCore.Graph>> tup;
3945 algorithm
3946 tup := matchcontinue tup
3947 local
3948 Absyn.Path path_1,pa,old_class_path,new_class_path;
3949 String new_name,id;
3950 Boolean changed;
3951 SourceInfo file_info;
3952 Absyn.Program p;
3953 list<Absyn.Path> path_lst;
3954 FCore.Graph env,cenv;
3955 Absyn.Class class_1,class_;
3956
3957 // Skip readonly classes.
3958 case (Absyn.CLASS(info = file_info), _, _)
3959 guard isReadOnly(file_info)
3960 ✗ then tup;
3961
3962 case (class_ as Absyn.CLASS(name = id), SOME(pa), (old_class_path,new_class_path,p,path_lst,env))
3963 algorithm
3964 ✗ path_1 := AbsynUtil.joinPaths(pa, Absyn.IDENT(id));
3965 ✗ true := AbsynUtil.pathEqual(old_class_path, path_1);
3966 ✗ new_name := AbsynUtil.pathLastIdent(new_class_path);
3967 ✗ class_.name := new_name;
3968 ✗ then
3969 ((class_,SOME(pa), (old_class_path,new_class_path,p, new_class_path :: path_lst, env)));
3970
3971 case (class_ as Absyn.CLASS(name = id), NONE(), (old_class_path,new_class_path,p,path_lst,env))
3972 algorithm
3973 ✗ path_1 := Absyn.IDENT(id);
3974 ✗ true := AbsynUtil.pathEqual(old_class_path, path_1);
3975 ✗ new_name := AbsynUtil.pathLastIdent(new_class_path);
3976 ✗ class_.name := new_name;
3977 ✗ then
3978 ((class_,NONE(), (old_class_path,new_class_path,p, new_class_path :: path_lst, env)));
3979
3980 case ((class_ as Absyn.CLASS(name = id)), SOME(pa), (old_class_path,new_class_path,p,path_lst,env))
3981 algorithm
3982 ✗ path_1 := AbsynUtil.joinPaths(pa, Absyn.IDENT(id));
3983 ✗ cenv := getClassEnvNoElaboration(p, path_1, env) "get_class_env(p,path\') => cenv &" ;
3984 ✗ (class_1,changed) := renameClassInClass(class_, old_class_path, new_class_path, cenv);
3985
3986 ✗ if changed then
3987 path_lst := path_1 :: path_lst;
3988 end if;
3989 ✗ then
3990 ((class_1,SOME(pa), (old_class_path,new_class_path,p, path_lst, env)));
3991
3992 case ((class_ as Absyn.CLASS(name = id)), NONE(), (old_class_path,new_class_path,p,path_lst,env))
3993 algorithm
3994 ✗ path_1 := Absyn.IDENT(id);
3995 ✗ cenv := getClassEnvNoElaboration(p, path_1, env) "get_class_env(p,path\') => cenv &" ;
3996 ✗ (class_1,changed) := renameClassInClass(class_, old_class_path, new_class_path, cenv);
3997
3998 ✗ if changed then
3999 path_lst := path_1 :: path_lst;
4000 end if;
4001 ✗ then
4002 ((class_1,NONE(), (old_class_path,new_class_path,p, path_lst, env)));
4003
4004 ✗ else tup;
4005 end matchcontinue;
4006 end renameClassVisitor;
4007
4008 protected function renameClassInClass
4009 "helper function to renameClassVisitor
4010 renames all the references to a class to another"
4011 input output Absyn.Class cls;
4012 input Absyn.Path oldName;
4013 input Absyn.Path newName;
4014 input FCore.Graph env;
4015 output Boolean changed;
4016 protected
4017 list<Absyn.ClassPart> parts;
4018 String name;
4019 Absyn.Path path;
4020 FCore.Graph cenv;
4021 FCore.Cache cache;
4022 Absyn.ClassDef body;
4023 Absyn.TypeSpec ty;
4024 algorithm
4025 ✗ body := cls.body;
4026
4027 changed := matchcontinue body
4028 case Absyn.PARTS(classParts = parts)
4029 algorithm
4030 ✗ (parts, changed) := renameClassInParts(parts, oldName, newName, env);
4031 ✗ body.classParts := parts;
4032 ✗ cls.body := body;
4033 ✗ then
4034 changed;
4035
4036 case Absyn.CLASS_EXTENDS(parts = parts)
4037 algorithm
4038 ✗ (parts, changed) := renameClassInParts(parts, oldName, newName, env);
4039 ✗ body.parts := parts;
4040 ✗ cls.body := body;
4041 ✗ then
4042 changed;
4043
4044 case Absyn.DERIVED(typeSpec = ty as Absyn.TPATH())
4045 algorithm
4046 ✗ (cache, SCode.CLASS(name=name),cenv) := Lookup.lookupClass(FCore.emptyCache(), env, ty.path);
4047 ✗ path := Absyn.IDENT(name);
4048 ✗ (_, path) := Inst.makeFullyQualified(cache, cenv, path);
4049 ✗ true := AbsynUtil.pathEqual(path, oldName);
4050 ✗ ty.path := changeLastIdent(path, newName);
4051 ✗ body.typeSpec := ty;
4052 ✗ cls.body := body;
4053 then
4054 true;
4055
4056 else false;
4057 end matchcontinue;
4058 end renameClassInClass;
4059
4060 protected function renameClassInParts
4061 "author: x02lucpo
4062 helper function to renameClassVisitor"
4063 input list<Absyn.ClassPart> parts;
4064 input Absyn.Path oldName;
4065 input Absyn.Path newName;
4066 input FCore.Graph env;
4067 output list<Absyn.ClassPart> outParts = {};
4068 output Boolean changed = false;
4069 protected
4070 Boolean c;
4071 list<Absyn.ElementItem> elems;
4072 algorithm
4073 ✗ for part in parts loop
4074 part := match part
4075 case Absyn.ClassPart.PUBLIC()
4076 algorithm
4077 ✗ (elems, c) := renameClassInElements(part.contents, oldName, newName, env);
4078 ✗ part.contents := elems;
4079 ✗ changed := changed or c;
4080 then
4081 part;
4082
4083 case Absyn.ClassPart.PROTECTED()
4084 algorithm
4085 ✗ (elems, c) := renameClassInElements(part.contents, oldName, newName, env);
4086 ✗ part.contents := elems;
4087 ✗ changed := changed or c;
4088 then
4089 part;
4090
4091 else part;
4092 end match;
4093
4094 outParts := part :: outParts;
4095 end for;
4096
4097 ✗ outParts := Dangerous.listReverseInPlace(outParts);
4098 end renameClassInParts;
4099
4100 protected function renameClassInElements
4101 input list<Absyn.ElementItem> items;
4102 input Absyn.Path oldName;
4103 input Absyn.Path newName;
4104 input FCore.Graph env;
4105 output list<Absyn.ElementItem> outItems = {};
4106 output Boolean changed = false;
4107 protected
4108 Absyn.Element elem;
4109 Absyn.ElementSpec spec;
4110 Boolean c;
4111 algorithm
4112 ✗ for item in items loop
4113 (outItems, changed) := match item
4114 case Absyn.ElementItem.ELEMENTITEM(element = elem as Absyn.Element.ELEMENT())
4115 algorithm
4116 ✗ (spec, c) := renameClassInElementSpec(elem.specification, oldName, newName, env);
4117 ✗ elem.specification := spec;
4118 ✗ item.element := elem;
4119 ✗ then
4120 (item :: outItems, changed or c);
4121
4122 else (item :: outItems, changed);
4123 end match;
4124 end for;
4125
4126 ✗ outItems := Dangerous.listReverseInPlace(outItems);
4127 end renameClassInElements;
4128
4129 protected function renameClassInElementSpec
4130 input output Absyn.ElementSpec spec;
4131 input Absyn.Path oldName;
4132 input Absyn.Path newName;
4133 input FCore.Graph env;
4134 output Boolean changed = false;
4135 protected
4136 Absyn.TypeSpec ty;
4137 FCore.Cache cache;
4138 String id;
4139 FCore.Graph cenv;
4140 Absyn.Path path, qpath;
4141 algorithm
4142 changed := matchcontinue spec
4143 case Absyn.COMPONENTS(typeSpec = ty as Absyn.TPATH())
4144 algorithm
4145 ✗ (cache, SCode.CLASS(name = id), cenv) := Lookup.lookupClass(FCore.emptyCache(), env, ty.path);
4146 ✗ (_, qpath) := Inst.makeFullyQualified(cache, cenv, Absyn.IDENT(id));
4147
4148 ✗ if AbsynUtil.pathEqual(qpath, oldName) then
4149 ✗ ty.path := changeLastIdent(qpath, newName);
4150 ✗ spec.typeSpec := ty;
4151 changed := true;
4152 end if;
4153 then
4154 changed;
4155
4156 case Absyn.EXTENDS()
4157 algorithm
4158 ✗ (cache, _, cenv) := Lookup.lookupClass(FCore.emptyCache(), env, spec.path);
4159 ✗ (_, qpath) := Inst.makeFullyQualified(cache, cenv, spec.path);
4160
4161 ✗ if AbsynUtil.pathEqual(qpath, oldName) then
4162 ✗ spec.path := changeLastIdent(spec.path, newName);
4163 changed := true;
4164 end if;
4165 then
4166 changed;
4167
4168 case Absyn.IMPORT()
4169 algorithm
4170 ✗ path := AbsynUtil.importPath(spec.import_);
4171 ✗ (cache, _, cenv) := Lookup.lookupClass(FCore.emptyCache(), env, path);
4172 ✗ (_, qpath) := Inst.makeFullyQualified(cache, cenv, path);
4173
4174 ✗ if AbsynUtil.pathEqual(qpath, oldName) then
4175 ✗ path := changeLastIdent(path, newName);
4176 ✗ spec.import_ := AbsynUtil.setImportPath(spec.import_, path);
4177 changed := true;
4178 end if;
4179 then
4180 changed;
4181
4182 else false;
4183 end matchcontinue;
4184 end renameClassInElementSpec;
4185
4186 public function refactorClass
4187 input Absyn.Path classPath;
4188 input Absyn.Program program;
4189 output Values.Value result;
4190 protected
4191 function impl
4192 input Absyn.Path classPath;
4193 input Absyn.Program program;
4194 input Access accessLevel;
4195 output Values.Value result;
4196 protected
4197 Absyn.Class cls;
4198 Absyn.Program p;
4199 String str;
4200 algorithm
4201 1 cls := ProgramUtil.getPathedClassInProgram(classPath, program);
4202 1 cls := Refactor.refactorGraphicalAnnotation(program, cls);
4203 1 p := ProgramUtil.updateProgram(Absyn.PROGRAM({cls}, Absyn.TOP()), program);
4204 1 SymbolTable.setAbsyn(p);
4205 1 str := Dump.unparseStr(Absyn.PROGRAM({cls}, Absyn.TOP()), false);
4206 1 result := ValuesMake.makeString(str);
4207 end impl;
4208 algorithm
4209 1 result := InteractiveUtil.accessClass(classPath, program, impl,
4210 evaluateParams = true, graphicsExpMode = true, accessLevel = Access.icon);
4211 end refactorClass;
4212
4213 protected function changeLastIdent
4214 "author: x02lucpo
4215 chages the last ident of the first path to the last path ident ie:
4216 (A.B.CC,C.DD) => (A.B.DD)"
4217 input Absyn.Path inPath1;
4218 input Absyn.Path inPath2;
4219 output Absyn.Path outPath;
4220 algorithm
4221 outPath:=
4222 match (inPath1,inPath2)
4223 local
4224 String b,b_1;
4225 Absyn.Path a_1,res,p1,p2;
4226 ✗ case (Absyn.IDENT(),Absyn.IDENT(name = b)) then Absyn.IDENT(b);
4227 case ((Absyn.IDENT()),(p2 as Absyn.QUALIFIED()))
4228 algorithm
4229 ✗ b_1 := AbsynUtil.pathLastIdent(p2);
4230 ✗ then
4231 Absyn.IDENT(b_1);
4232 case ((p1 as Absyn.QUALIFIED()),(p2 as Absyn.IDENT()))
4233 algorithm
4234 ✗ a_1 := AbsynUtil.stripLast(p1);
4235 ✗ res := AbsynUtil.joinPaths(a_1, p2);
4236 then
4237 res;
4238 case ((p1 as Absyn.QUALIFIED()),(p2 as Absyn.QUALIFIED()))
4239 algorithm
4240 ✗ a_1 := AbsynUtil.stripLast(p1);
4241 ✗ b_1 := AbsynUtil.pathLastIdent(p2);
4242 ✗ res := AbsynUtil.joinPaths(a_1, Absyn.IDENT(b_1));
4243 then
4244 res;
4245 end match;
4246 end changeLastIdent;
4247
4248 public function isPrimitive
4249 "Thisfunction takes a component reference and a program.
4250 It returns the true if the refrenced type is a primitive
4251 type, otherwise it returns false."
4252 input Absyn.Path className;
4253 input Absyn.Program inProgram;
4254 output Boolean outBoolean;
4255 algorithm
4256 outBoolean := match className
4257 local
4258 Absyn.Class class_;
4259 /* Instead of elaborating and lookup these in env, we optimize a bit and just return true for these */
4260 case Absyn.IDENT(name = "Real") then true;
4261 case Absyn.IDENT(name = "Integer") then true;
4262 case Absyn.IDENT(name = "String") then true;
4263 case Absyn.IDENT(name = "Boolean") then true;
4264 case _
4265 algorithm
4266 1 class_ := ProgramUtil.getPathedClassInProgram(className, inProgram);
4267 1 then
4268 isPrimitiveClass(class_, inProgram);
4269 else false;
4270 end match;
4271 end isPrimitive;
4272
4273 public function createModel
4274 input Absyn.Path className;
4275 input Absyn.Program inProgram;
4276 output Absyn.Program outProgram;
4277 protected
4278 Absyn.Ident name;
4279 Absyn.Within w;
4280 Absyn.Path wp;
4281 algorithm
4282
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
8 if AbsynUtil.pathIsIdent(className) then
4283 6 name := AbsynUtil.pathFirstIdent(className);
4284 w := Absyn.TOP();
4285 else
4286
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 (wp, Absyn.IDENT(name)) := AbsynUtil.splitQualAndIdentPath(className);
4287 2 w := Absyn.WITHIN(wp);
4288 end if;
4289
4290 16 outProgram := ProgramUtil.updateProgram(Absyn.PROGRAM({
4291 Absyn.CLASS(name, false, false, false, Absyn.R_MODEL(), Absyn.dummyParts,
4292 {}, {}, {}, Absyn.dummyInfo)}, w), inProgram);
4293 end createModel;
4294
4295 public function newModel
4296 input Absyn.Path className;
4297 input Absyn.Path withinPath;
4298 input output Absyn.Program program;
4299 algorithm
4300 ✗ program := createModel(AbsynUtil.joinPaths(withinPath, className), program);
4301 end newModel;
4302
4303 public function deleteClass
4304 "Deletes the given class from the program."
4305 input Absyn.Path classPath;
4306 input Absyn.Program inProgram;
4307 output Boolean success;
4308 output Absyn.Program outProgram = inProgram;
4309 algorithm
4310 (success, outProgram) := matchcontinue inProgram
4311 local
4312 Absyn.Path parentcpath,parentparentcpath;
4313 Absyn.Class cdef,parentcdef,parentcdef_1;
4314
4315 case _
4316 algorithm
4317 //Class inside another class, inside another class
4318 4 parentcpath := AbsynUtil.stripLast(classPath);
4319 1 parentparentcpath := AbsynUtil.stripLast(parentcpath);
4320 ✗ cdef := ProgramUtil.getPathedClassInProgram(classPath, inProgram);
4321 ✗ parentcdef := ProgramUtil.getPathedClassInProgram(parentcpath, inProgram);
4322 ✗ parentcdef_1 := InteractiveUtil.removeInnerClass(cdef, parentcdef);
4323 ✗ outProgram := ProgramUtil.updateProgram(Absyn.PROGRAM({parentcdef_1},Absyn.WITHIN(parentparentcpath)), inProgram);
4324 then
4325 (true, outProgram);
4326 case _
4327 algorithm
4328 // Class inside other class
4329 4 parentcpath := AbsynUtil.stripLast(classPath);
4330 1 cdef := ProgramUtil.getPathedClassInProgram(classPath, inProgram);
4331 1 parentcdef := ProgramUtil.getPathedClassInProgram(parentcpath, inProgram);
4332 1 parentcdef_1 := InteractiveUtil.removeInnerClass(cdef, parentcdef);
4333 1 outProgram := ProgramUtil.updateProgram(Absyn.PROGRAM({parentcdef_1},Absyn.TOP()), inProgram);
4334 then
4335 (true, outProgram);
4336 case _
4337 algorithm
4338 // Top level class
4339 3 cdef := ProgramUtil.getPathedClassInProgram(classPath, inProgram);
4340 3 outProgram.classes := List.deleteMemberOnTrue(AbsynUtil.className(cdef),
4341 outProgram.classes, AbsynUtil.isClassNamed);
4342 then
4343 (true, outProgram);
4344
4345 else (false,inProgram);
4346 end matchcontinue;
4347 end deleteClass;
4348
4349 public function setClassComment
4350 "author: PA
4351 Sets the class comment."
4352 input Absyn.Path path;
4353 input String inString;
4354 input Absyn.Program inProgram;
4355 output Absyn.Program outProgram;
4356 output Boolean success;
4357 algorithm
4358 (outProgram,success) := matchcontinue (path,inString,inProgram)
4359 local
4360 Absyn.Path p_class;
4361 Absyn.Within within_;
4362 Absyn.Class cdef,cdef_1;
4363 Absyn.Program newp,p;
4364 String str;
4365
4366 case (p_class,str,p as Absyn.PROGRAM())
4367 algorithm
4368 2 within_ := ProgramUtil.buildWithin(p_class);
4369 2 cdef := ProgramUtil.getPathedClassInProgram(p_class, p);
4370 2 cdef_1 := setClassCommentInClass(cdef, str);
4371 2 newp := ProgramUtil.updateProgram(Absyn.PROGRAM({cdef_1},within_), p);
4372 then
4373 (newp,true);
4374
4375 else (inProgram,false);
4376 end matchcontinue;
4377 end setClassComment;
4378
4379 protected function setClassCommentInClass
4380 "Helper function to setClassComment"
4381 input output Absyn.Class cls;
4382 input String commentString;
4383 algorithm
4384 2 cls.body := setClassCommentInClassdef(cls.body, commentString);
4385 end setClassCommentInClass;
4386
4387 protected function setClassCommentInClassdef
4388 "Helper function to setClassCommentInClass"
4389 input output Absyn.ClassDef classDef;
4390 input String commentString;
4391 protected
4392 Option<String> cmt_str;
4393 algorithm
4394
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 cmt_str := if stringEmpty(commentString) then NONE() else SOME(commentString);
4395
4396 () := match classDef
4397 case Absyn.ClassDef.PARTS()
4398 algorithm
4399 2 classDef.comment := cmt_str;
4400 then
4401 ();
4402
4403 case Absyn.ClassDef.DERIVED()
4404 algorithm
4405 ✗ classDef.comment := AbsynUtil.setCommentString(classDef.comment, cmt_str);
4406 then
4407 ();
4408
4409 case Absyn.ClassDef.ENUMERATION()
4410 algorithm
4411 ✗ classDef.comment := AbsynUtil.setCommentString(classDef.comment, cmt_str);
4412 then
4413 ();
4414
4415 case Absyn.ClassDef.OVERLOAD()
4416 algorithm
4417 ✗ classDef.comment := AbsynUtil.setCommentString(classDef.comment, cmt_str);
4418 then
4419 ();
4420
4421 case Absyn.ClassDef.CLASS_EXTENDS()
4422 algorithm
4423 ✗ classDef.comment := cmt_str;
4424 then
4425 ();
4426
4427 case Absyn.ClassDef.PDER()
4428 algorithm
4429 ✗ classDef.comment := AbsynUtil.setCommentString(classDef.comment, cmt_str);
4430 then
4431 ();
4432
4433 else ();
4434 end match;
4435 end setClassCommentInClassdef;
4436
4437 public function getShortDefinitionBaseClassInformation
4438 input Absyn.Path classPath;
4439 input Absyn.Program program;
4440 output Values.Value result;
4441 protected
4442 Absyn.TypeSpec ty;
4443 Absyn.ElementAttributes attr;
4444 list<Values.Value> vals = {};
4445 algorithm
4446 try
4447 ✗ Absyn.CLASS(body = Absyn.DERIVED(typeSpec = ty, attributes = attr as Absyn.ATTR())) :=
4448 ProgramUtil.getPathedClassInProgram(classPath, program);
4449 ✗ vals := ValuesMake.makeArray(InteractiveUtil.dimensionListValues(AbsynUtil.typeSpecDimensions(ty))) :: vals;
4450 ✗ vals := ValuesMake.makeString(InteractiveUtil.attrDirectionStr(attr)) :: vals;
4451 ✗ vals := ValuesMake.makeString(InteractiveUtil.attrVariabilityStr(attr)) :: vals;
4452 ✗ vals := ValuesMake.makeString(if attr.streamPrefix then "stream" else "") :: vals;
4453 ✗ vals := ValuesMake.makeString(if attr.flowPrefix then "flow" else "") :: vals;
4454 ✗ vals := ValuesMake.makeCodeTypeName(AbsynUtil.typeSpecPath(ty)) :: vals;
4455 else
4456 vals := {};
4457 end try;
4458
4459 ✗ result := ValuesMake.makeArray(vals);
4460 end getShortDefinitionBaseClassInformation;
4461
4462 public function getExternalFunctionSpecification
4463 input Absyn.Path functionName;
4464 input Absyn.Program program;
4465 output Values.Value result;
4466 protected
4467 Absyn.Class cls;
4468 Absyn.ExternalDecl ext_decl;
4469 Option<Absyn.Annotation> ann;
4470 list<Values.Value> vals = {};
4471 algorithm
4472 try
4473 ✗ cls := ProgramUtil.getPathedClassInProgram(functionName, program);
4474 ✗ Absyn.EXTERNAL(ext_decl, ann) := AbsynUtil.getExternalDecl(cls);
4475
4476 ✗ vals := ValuesMake.makeString(Dump.unparseAnnotationOption(ann)) :: vals;
4477 ✗ vals := ValuesMake.makeString(Dump.unparseAnnotationOption(ext_decl.annotation_)) :: vals;
4478 ✗ vals := ValuesMake.makeString(Dump.printExpLstStr(ext_decl.args)) :: vals;
4479 ✗ vals := ValuesMake.makeString(Util.getOptionOrDefault(ext_decl.funcName, "")) :: vals;
4480 ✗ vals := ValuesMake.makeString(Util.applyOptionOrDefault(ext_decl.output_, Dump.printComponentRefStr, "")) :: vals;
4481 ✗ vals := ValuesMake.makeString(Util.getOptionOrDefault(ext_decl.lang, "")) :: vals;
4482 else
4483 vals := {};
4484 end try;
4485
4486 ✗ result := ValuesMake.makeArray(vals);
4487 end getExternalFunctionSpecification;
4488
4489 protected function getClassDimensions
4490 "Returns the dimensions of a class as vector of dimension sizes in a string.
4491 Note: A class can only have dimensions if it is a short class definition."
4492 input Absyn.ClassDef cdef;
4493 output String str;
4494 protected
4495 Absyn.ArrayDim ad;
4496 algorithm
4497 str := match cdef
4498 case Absyn.DERIVED(typeSpec = Absyn.TPATH(arrayDim = SOME(ad)))
4499 ✗ then List.toString(ad, Dump.printSubscriptStr, List.Style.FLAT_CURLY);
4500 else "{}";
4501 end match;
4502 end getClassDimensions;
4503
4504 public function getClassRestriction
4505 "Returns the class restriction of a class as a string."
4506 input Absyn.Path path;
4507 input Absyn.Program program;
4508 output String outRestriction;
4509 protected
4510 Absyn.Restriction restr;
4511 algorithm
4512 try
4513 ✗ Absyn.CLASS(restriction = restr) := ProgramUtil.getPathedClassInProgram(path, program);
4514 ✗ outRestriction := Dump.unparseRestrictionStr(restr);
4515 else
4516 outRestriction := "";
4517 end try;
4518 end getClassRestriction;
4519
4520 public function isType
4521 "Returns true if the referenced class has the restriction 'type', otherwise false."
4522 input Absyn.Path path;
4523 input Absyn.Program program;
4524 output Boolean res;
4525 algorithm
4526 res := match InteractiveUtil.getPathedClassRestriction(path, program)
4527 case Absyn.R_TYPE() then true;
4528 else false;
4529 end match;
4530 end isType;
4531
4532 public function isConnector
4533 "Returns true if the referenced class has the restriction 'connector' or
4534 'expandable connector', otherwise false."
4535 input Absyn.Path path;
4536 input Absyn.Program program;
4537 output Boolean res;
4538 algorithm
4539 res := match InteractiveUtil.getPathedClassRestriction(path, program)
4540 case Absyn.R_CONNECTOR() then true;
4541 case Absyn.R_EXP_CONNECTOR() then true;
4542 else false;
4543 end match;
4544 end isConnector;
4545
4546 public function isModel
4547 "Returns true if the referenced class has the restriction 'model', otherwise false."
4548 input Absyn.Path path;
4549 input Absyn.Program program;
4550 output Boolean res;
4551 algorithm
4552 res := match InteractiveUtil.getPathedClassRestriction(path, program)
4553 case Absyn.R_MODEL() then true;
4554 else false;
4555 end match;
4556 end isModel;
4557
4558 public function isOperator
4559 "Returns true if the referenced class has the restriction 'operator', otherwise false."
4560 input Absyn.Path path;
4561 input Absyn.Program program;
4562 output Boolean res;
4563 algorithm
4564 res := match InteractiveUtil.getPathedClassRestriction(path, program)
4565 case Absyn.R_OPERATOR() then true;
4566 else false;
4567 end match;
4568 end isOperator;
4569
4570 public function isOperatorRecord
4571 "Returns true if the referenced class has the restriction 'operator record', otherwise false."
4572 input Absyn.Path path;
4573 input Absyn.Program program;
4574 output Boolean res;
4575 algorithm
4576 res := match InteractiveUtil.getPathedClassRestriction(path, program)
4577 case Absyn.R_OPERATOR_RECORD() then true;
4578 else false;
4579 end match;
4580 end isOperatorRecord;
4581
4582 public function isOperatorFunction
4583 "Returns true if the referenced class has the restriction 'operator function', otherwise false."
4584 input Absyn.Path path;
4585 input Absyn.Program program;
4586 output Boolean res;
4587 algorithm
4588 res := match InteractiveUtil.getPathedClassRestriction(path, program)
4589 case Absyn.R_FUNCTION(Absyn.FR_OPERATOR_FUNCTION()) then true;
4590 else false;
4591 end match;
4592 end isOperatorFunction;
4593
4594 public function isRecord
4595 "Returns true if the referenced class has the restriction 'record', otherwise false."
4596 input Absyn.Path path;
4597 input Absyn.Program program;
4598 output Boolean res;
4599 algorithm
4600 res := match InteractiveUtil.getPathedClassRestriction(path, program)
4601 case Absyn.R_RECORD() then true;
4602 else false;
4603 end match;
4604 end isRecord;
4605
4606 public function isBlock
4607 "Returns true if the referenced class has the restriction 'block', otherwise false."
4608 input Absyn.Path path;
4609 input Absyn.Program program;
4610 output Boolean res;
4611 algorithm
4612 res := match InteractiveUtil.getPathedClassRestriction(path, program)
4613 case Absyn.R_BLOCK() then true;
4614 else false;
4615 end match;
4616 end isBlock;
4617
4618 public function isOptimization
4619 "Returns true if the referenced class has the restriction 'optimization', otherwise false."
4620 input Absyn.Path path;
4621 input Absyn.Program program;
4622 output Boolean res;
4623 algorithm
4624 res := match InteractiveUtil.getPathedClassRestriction(path, program)
4625 case Absyn.R_OPTIMIZATION() then true;
4626 else false;
4627 end match;
4628 end isOptimization;
4629
4630 public function isFunction
4631 "Returns true if the referenced class has the restriction 'function', otherwise false."
4632 input Absyn.Path path;
4633 input Absyn.Program program;
4634 output Boolean res;
4635 algorithm
4636 res := match InteractiveUtil.getPathedClassRestriction(path, program)
4637 case Absyn.R_FUNCTION(Absyn.FR_NORMAL_FUNCTION()) then true;
4638 else false;
4639 end match;
4640 end isFunction;
4641
4642 public function isPackage
4643 "Returns true if the referenced class has the restriction 'package', otherwise false."
4644 input Absyn.Path path;
4645 input Absyn.Program program;
4646 output Boolean res;
4647 algorithm
4648 res := match InteractiveUtil.getPathedClassRestriction(path, program)
4649 case Absyn.R_PACKAGE() then true;
4650 else false;
4651 end match;
4652 end isPackage;
4653
4654 public function isClass
4655 "Returns true if the referenced class has the restriction 'class', otherwise false."
4656 input Absyn.Path path;
4657 input Absyn.Program program;
4658 output Boolean res;
4659 algorithm
4660 res := match InteractiveUtil.getPathedClassRestriction(path, program)
4661 case Absyn.R_CLASS() then true;
4662 else false;
4663 end match;
4664 end isClass;
4665
4666 public function isPartial
4667 "Returns true if the referenced class is partial, otherwise false."
4668 input Absyn.Path path;
4669 input Absyn.Program program;
4670 output Boolean res;
4671 algorithm
4672 try
4673
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
17 Absyn.CLASS(partialPrefix=true) := ProgramUtil.getPathedClassInProgram(path, program);
4674 res := true;
4675 else
4676 res := false;
4677 end try;
4678 end isPartial;
4679
4680 public function isReplaceable
4681 "Returns true if the referenced element is replaceable, otherwise false."
4682 input Absyn.Path path;
4683 input Absyn.Program program;
4684 output Boolean res;
4685 algorithm
4686 try
4687 ✗ res := AbsynUtil.isElementReplaceable(InteractiveUtil.getPathedElementInProgram(path, program));
4688 else
4689 res := false;
4690 end try;
4691 end isReplaceable;
4692
4693 public function isRedeclare
4694 "Returns true if the referenced element is a redeclare, otherwise false."
4695 input Absyn.Path path;
4696 input Absyn.Program program;
4697 output Boolean res;
4698 algorithm
4699 try
4700 5 res := AbsynUtil.isElementRedeclare(InteractiveUtil.getPathedElementInProgram(path, program));
4701 else
4702 res := false;
4703 end try;
4704 end isRedeclare;
4705
4706 public function isParameter
4707 "This function takes a class and a component reference and a program
4708 and returns true if the component referenced is a parameter."
4709 input Absyn.Path componentName;
4710 input Absyn.Path className;
4711 input Absyn.Program program;
4712 output Boolean res;
4713 protected
4714 Absyn.Path path;
4715 algorithm
4716 try
4717 ✗ path := AbsynUtil.joinPaths(className, componentName);
4718 ✗ Absyn.ELEMENT(specification = Absyn.COMPONENTS(attributes = Absyn.ATTR(variability = Absyn.PARAM()))) :=
4719 InteractiveUtil.getPathedElementInProgram(path, program);
4720 res := true;
4721 else
4722 res := false;
4723 end try;
4724 end isParameter;
4725
4726 public function isConstant
4727 "This function takes a class and a component reference and a program
4728 and returns true if the component referenced is a constant."
4729 input Absyn.Path componentName;
4730 input Absyn.Path className;
4731 input Absyn.Program program;
4732 output Boolean res;
4733 protected
4734 Absyn.Path path;
4735 algorithm
4736 try
4737 ✗ path := AbsynUtil.joinPaths(className, componentName);
4738 ✗ Absyn.ELEMENT(specification = Absyn.COMPONENTS(attributes = Absyn.ATTR(variability = Absyn.CONST()))) :=
4739 InteractiveUtil.getPathedElementInProgram(path, program);
4740 res := true;
4741 else
4742 res := false;
4743 end try;
4744 end isConstant;
4745
4746 public function isProtected
4747 "This function takes a class and a component reference and a program
4748 and returns true if the component referenced is in a protected section."
4749 input Absyn.Path componentName;
4750 input Absyn.Path className;
4751 input Absyn.Program program;
4752 output Boolean res;
4753 protected
4754 list<Absyn.ClassPart> parts;
4755 list<Absyn.ElementItem> items;
4756 algorithm
4757 try
4758 ✗ parts := AbsynUtil.getClassPartsInClass(ProgramUtil.getPathedClassInProgram(className, program));
4759 ✗ items := ProgramUtil.getProtectedList(parts);
4760 ✗ getComponentsContainsName(AbsynUtil.pathToCref(componentName), items);
4761 res := true;
4762 else
4763 res := false;
4764 end try;
4765 end isProtected;
4766
4767 public function isEnumeration
4768 "Returns true if the referenced class is an enumeration, otherwise false."
4769 input Absyn.Path path;
4770 input Absyn.Program program;
4771 output Boolean res;
4772 algorithm
4773 try
4774 ✗ Absyn.CLASS(restriction = Absyn.R_TYPE(), body = Absyn.ENUMERATION()) :=
4775 ProgramUtil.getPathedClassInProgram(path, program);
4776 res := true;
4777 else
4778 res := false;
4779 end try;
4780 end isEnumeration;
4781
4782 public function isProtectedClass
4783 "Returns true if the class referenced by className within path is protected.
4784 Only look to Element Items of inComponentRef1 for components use getComponents."
4785 input Absyn.Path path;
4786 input String className;
4787 input Absyn.Program program;
4788 output Boolean res;
4789 protected
4790 list<Absyn.ClassPart> parts;
4791 list<Absyn.ElementItem> items;
4792 algorithm
4793 try
4794 4 parts := AbsynUtil.getClassPartsInClass(ProgramUtil.getPathedClassInProgram(path, program));
4795 4 items := ProgramUtil.getProtectedList(parts);
4796 4 res := isProtectedClassInElements(items, className);
4797 else
4798 res := false;
4799 end try;
4800 end isProtectedClass;
4801
4802 protected function isProtectedClassInElements
4803 "Helper function to isProtectedClass."
4804 input list<Absyn.ElementItem> items;
4805 input String className;
4806 output Boolean res = false;
4807 protected
4808 String name;
4809 algorithm
4810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 for item in items loop
4811 res := match item
4812 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification =
4813 Absyn.CLASSDEF(class_ = Absyn.CLASS(name = name))))
4814 ✗ then name == className;
4815 else false;
4816 end match;
4817
4818 if res then
4819 break;
4820 end if;
4821 end for;
4822 end isProtectedClassInElements;
4823
4824 public function getEnumerationLiterals
4825 input Absyn.Path classPath;
4826 input Absyn.Program program;
4827 output Values.Value result;
4828 protected
4829 list<Absyn.EnumLiteral> literals;
4830 list<String> names;
4831 algorithm
4832 try
4833 ✗ Absyn.CLASS(body = Absyn.ENUMERATION(enumLiterals = Absyn.ENUMLITERALS(enumLiterals = literals))) :=
4834 ProgramUtil.getPathedClassInProgram(classPath, program);
4835 ✗ names := list(AbsynUtil.enumLiteralName(l) for l in literals);
4836 else
4837 names := {};
4838 end try;
4839
4840 ✗ result := ValuesMake.makeStringArray(names);
4841 end getEnumerationLiterals;
4842
4843 public function getDerivedClassModifierNames
4844 "Returns the derived class modifier names."
4845 input Absyn.Class inClass;
4846 output list<String> outString;
4847 protected
4848 list<Absyn.ElementArg> args;
4849 algorithm
4850 outString := match inClass
4851 case Absyn.CLASS(restriction = Absyn.R_TYPE(), body = Absyn.DERIVED(arguments = args))
4852 ✗ then getModificationNames(args);
4853 else {};
4854 end match;
4855 end getDerivedClassModifierNames;
4856
4857 public function getDerivedClassModifierValue
4858 "Returns the derived class modifier value."
4859 input Absyn.Class cls;
4860 input Absyn.Path path;
4861 output String value;
4862 protected
4863 list<Absyn.ElementArg> args;
4864 algorithm
4865 try
4866 ✗ Absyn.CLASS(body = Absyn.DERIVED(arguments = args)) := cls;
4867 ✗ value := Dump.printExpStr(getModificationValue(args, path));
4868 else
4869 value := "";
4870 end try;
4871 end getDerivedClassModifierValue;
4872
4873 protected function getElementitemContainsName
4874 "Returns the element that has the component name given as argument."
4875 input Absyn.ComponentRef inComponentRef;
4876 input list<Absyn.ElementItem> inAbsynElementItemLst;
4877 output Absyn.ElementItem outElementItem;
4878 algorithm
4879 outElementItem:=
4880 matchcontinue (inComponentRef,inAbsynElementItemLst)
4881 local
4882 Absyn.ComponentRef cr;
4883 Absyn.ElementItem elt,res;
4884 list<Absyn.ElementItem> rest;
4885 case (cr,(elt :: _))
4886 algorithm
4887 ✗ getComponentsContainsName(cr, {elt});
4888 then
4889 elt;
4890 case (cr,(_ :: rest))
4891 algorithm
4892 ✗ res := getElementitemContainsName(cr, rest);
4893 then
4894 res;
4895 end matchcontinue;
4896 end getElementitemContainsName;
4897
4898 protected function getComponentsContainsName
4899 "Return the ElementSpec containing the name
4900 given as argument from a list of ElementItems"
4901 input Absyn.ComponentRef inComponentRef;
4902 input list<Absyn.ElementItem> inAbsynElementItemLst;
4903 output Absyn.ElementSpec outElementSpec;
4904 algorithm
4905 outElementSpec:=
4906 matchcontinue (inComponentRef,inAbsynElementItemLst)
4907 local
4908 Absyn.ComponentRef cr;
4909 Absyn.ElementSpec res;
4910 list<Absyn.ComponentItem> ellst;
4911 list<Absyn.ElementItem> xs;
4912 case (cr,(Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = (res as Absyn.COMPONENTS(components = ellst)))) :: _))
4913 algorithm
4914 ✗ getCompitemNamed(cr, ellst);
4915 then
4916 res;
4917 case (cr,(_ :: xs))
4918 algorithm
4919 ✗ res := getComponentsContainsName(cr, xs);
4920 then
4921 res;
4922 end matchcontinue;
4923 end getComponentsContainsName;
4924
4925 protected function getElementContainsName
4926 "Return the Element containing the component name
4927 given as argument from a list of ElementItems."
4928 input Absyn.ComponentRef inComponentRef;
4929 input list<Absyn.ElementItem> inAbsynElementItemLst;
4930 output Absyn.Element outElement;
4931 algorithm
4932 outElement:=
4933 matchcontinue (inComponentRef,inAbsynElementItemLst)
4934 local
4935 Absyn.ComponentRef cr;
4936 Absyn.Element res;
4937 list<Absyn.ComponentItem> ellst;
4938 list<Absyn.ElementItem> xs;
4939 case (cr,(Absyn.ELEMENTITEM(element = (res as Absyn.ELEMENT(specification = Absyn.COMPONENTS(components = ellst)))) :: _))
4940 algorithm
4941 8 getCompitemNamed(cr, ellst);
4942 then
4943 res;
4944 case (cr,(_ :: xs))
4945 algorithm
4946 3 res := getElementContainsName(cr, xs);
4947 then
4948 res;
4949 end matchcontinue;
4950 end getElementContainsName;
4951
4952 protected function getCompitemNamed
4953 "Helper function to getComponentsContainsName."
4954 input Absyn.ComponentRef inComponentRef;
4955 input list<Absyn.ComponentItem> inAbsynComponentItemLst;
4956 output Absyn.ComponentItem outComponentItem;
4957 algorithm
4958 outComponentItem := matchcontinue (inComponentRef,inAbsynComponentItemLst)
4959 local
4960 String id1,id2;
4961 Absyn.ComponentItem x,res;
4962 list<Absyn.ComponentItem> xs;
4963 Absyn.ComponentRef cr;
4964
4965 case (Absyn.CREF_IDENT(name = id1),((x as Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = id2))) :: _))
4966 algorithm
4967
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 2 times.
13 true := stringEq(id1, id2);
4968 then
4969 x;
4970
4971 case (cr,(_ :: xs))
4972 algorithm
4973 3 res := getCompitemNamed(cr, xs);
4974 then
4975 res;
4976 end matchcontinue;
4977 end getCompitemNamed;
4978
4979 public function existClass
4980 "Returns true if the referenced class exists in the program, otherwise false."
4981 input Absyn.Path classPath;
4982 input Absyn.Program program;
4983 output Boolean res;
4984 algorithm
4985 try
4986 27 ProgramUtil.getPathedClassInProgram(classPath, program);
4987 res := true;
4988 else
4989 res := false;
4990 end try;
4991 end existClass;
4992
4993 public function isPrimitiveClass
4994 "Return true of a class is a primitive class, i.e. one of the builtin
4995 classes or the \'type\' restricted class. It also checks derived classes
4996 using short class definition."
4997 input Absyn.Class inClass;
4998 input Absyn.Program inProgram;
4999 output Boolean outBoolean;
5000 algorithm
5001 outBoolean:=
5002 match (inClass,inProgram)
5003 local
5004 Absyn.Path inmodel,path;
5005 Absyn.Class cdef;
5006 Boolean res;
5007 String cname;
5008 Absyn.Program p;
5009 case (Absyn.CLASS(restriction = Absyn.R_PREDEFINED_INTEGER()),_) then true;
5010 case (Absyn.CLASS(restriction = Absyn.R_PREDEFINED_REAL()),_) then true;
5011 case (Absyn.CLASS(restriction = Absyn.R_PREDEFINED_STRING()),_) then true;
5012 case (Absyn.CLASS(restriction = Absyn.R_PREDEFINED_BOOLEAN()),_) then true;
5013 // BTH
5014 case (Absyn.CLASS(restriction = Absyn.R_PREDEFINED_CLOCK()),_) then true;
5015 case (Absyn.CLASS(restriction = Absyn.R_TYPE()),_) then true;
5016 case (Absyn.CLASS(name = cname,restriction = Absyn.R_CLASS(),body = Absyn.DERIVED(typeSpec = Absyn.TPATH(path,_))),p)
5017 algorithm
5018 ✗ inmodel := AbsynUtil.crefToPath(Absyn.CREF_IDENT(cname,{}));
5019 ✗ (cdef,_) := lookupClassdef(path, inmodel, p);
5020 ✗ res := isPrimitiveClass(cdef, p);
5021 then
5022 res;
5023 else false;
5024 end match;
5025 end isPrimitiveClass;
5026
5027 public function addScope
5028 " This function adds the scope of the scope variable to
5029 the program, so it can be inserted at the correct place.
5030 It also adds the scope to BEGIN_DEFINITION, COMP_DEFINITION
5031 and IMPORT_DEFINITION so an empty class definition can be
5032 inserted at the correct place."
5033 input Absyn.Program inProgram;
5034 input list<InteractiveTypes.Variable> inVariableLst;
5035 output Absyn.Program outProgram;
5036 algorithm
5037 outProgram:=
5038 matchcontinue (inProgram,inVariableLst)
5039 local
5040 Absyn.Path path,newpath,path2;
5041 list<Absyn.Class> cls;
5042 list<InteractiveTypes.Variable> vars;
5043 Absyn.Within w;
5044
5045 case (Absyn.PROGRAM(classes = cls,within_ = Absyn.TOP()),vars)
5046 algorithm
5047 ✗ Values.CODE(Absyn.C_TYPENAME(path)) := getVariableValue("scope", vars);
5048 ✗ then
5049 Absyn.PROGRAM(cls,Absyn.WITHIN(path));
5050
5051 case (Absyn.PROGRAM(classes = cls,within_ = w),vars)
5052 algorithm
5053 ✗ failure(getVariableValue("scope", vars));
5054 ✗ then
5055 Absyn.PROGRAM(cls,w);
5056 case (Absyn.PROGRAM(classes = cls,within_ = Absyn.WITHIN(path = path2)),vars)
5057 algorithm
5058 ✗ Values.CODE(Absyn.C_TYPENAME(path)) := getVariableValue("scope", vars) "This should probably be forbidden." ;
5059 ✗ newpath := AbsynUtil.joinPaths(path, path2);
5060 ✗ then
5061 Absyn.PROGRAM(cls,Absyn.WITHIN(newpath));
5062 else inProgram;
5063 end matchcontinue;
5064 end addScope;
5065
5066 protected function getVariableValue
5067 "Return the value of an interactive variable
5068 from a list of InteractiveTypes.Variable."
5069 input Absyn.Ident inIdent;
5070 input list<InteractiveTypes.Variable> inVariableLst;
5071 output Values.Value outValue;
5072 algorithm
5073 outValue := matchcontinue (inIdent,inVariableLst)
5074 local
5075 String id1,id2;
5076 Values.Value v;
5077 list<InteractiveTypes.Variable> rest;
5078
5079 case (id1,(InteractiveTypes.IVAR(varIdent = id2,value = v) :: _))
5080 algorithm
5081 ✗ true := stringEq(id1, id2);
5082 then
5083 v;
5084
5085 case (id1,(InteractiveTypes.IVAR(varIdent = id2) :: rest))
5086 algorithm
5087 ✗ false := stringEq(id1, id2);
5088 ✗ v := getVariableValue(id1, rest);
5089 then
5090 v;
5091 end matchcontinue;
5092 end getVariableValue;
5093
5094 protected function getVariableValueLst
5095 "Return the value of an interactive variable
5096 from a list of InteractiveTypes.Variable."
5097 input list<String> ids;
5098 input list<InteractiveTypes.Variable> vars;
5099 output Values.Value val;
5100 algorithm
5101 val := matchcontinue (ids,vars)
5102 local
5103 Integer ix;
5104 String id1,id2,id3;
5105 Values.Value v;
5106 list<InteractiveTypes.Variable> rest;
5107 list<String> comp,srest;
5108 list<Values.Value> vals;
5109
5110 case (id1::_, (InteractiveTypes.IVAR(varIdent = id2) :: rest))
5111 algorithm
5112
4/4
✓ Branch 0 taken 1690 times.
✓ Branch 1 taken 8749 times.
✓ Branch 3 taken 1340 times.
✓ Branch 4 taken 350 times.
10439 false := stringEq(id1, id2);
5113 9099 v := getVariableValueLst(ids, rest);
5114 then
5115 v;
5116
5117 case (id1::id2::srest, (InteractiveTypes.IVAR(varIdent = id3,value = Values.RECORD(orderd = vals, comp = comp)) :: _))
5118 algorithm
5119
2/4
✓ Branch 0 taken 430 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 430 times.
430 true := stringEq(id1, id3);
5120 430 ix := List.position1OnTrue(comp, stringEq, id2);
5121 430 v := listGet(vals, ix);
5122 860 v := getVariableValueLst(id2::srest, {InteractiveTypes.IVAR(id2,v,DAE.T_UNKNOWN_DEFAULT)});
5123 then
5124 v;
5125
5126 case ({id1}, (InteractiveTypes.IVAR(varIdent = id2,value = v) :: _))
5127 algorithm
5128
2/4
✓ Branch 0 taken 910 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 910 times.
910 true := stringEq(id1, id2);
5129 then
5130 v;
5131
5132 end matchcontinue;
5133 end getVariableValueLst;
5134
5135 protected function lookupClassdef
5136 " This function takes a Path of a class to lookup and a Path
5137 as a starting point for the lookup rules and a Program.
5138 It returns the Class definition and the complete Path to the class."
5139 input Absyn.Path inPath1;
5140 input Absyn.Path inPath2;
5141 input Absyn.Program inProgram3;
5142 output Absyn.Class outClass;
5143 output Absyn.Path outPath;
5144 algorithm
5145 (outClass,outPath) := matchcontinue (inPath1,inPath2,inProgram3)
5146 local
5147 Absyn.Class inmodeldef,cdef;
5148 Absyn.Path newpath,path,inmodel,innewpath,respath;
5149 Absyn.Program p;
5150 String s1,s2;
5151
5152 case (path,inmodel,p as Absyn.PROGRAM())
5153 algorithm
5154 //fprintln(Flags.INTER, "Interactive.lookupClassdef 1 Looking for: " + AbsynUtil.pathString(path) + " in: " + AbsynUtil.pathString(inmodel));
5155 // remove self reference, otherwise we go into an infinite loop!
5156 7 path := InstUtil.removeSelfReference(AbsynUtil.pathLastIdent(inmodel),path);
5157 7 inmodeldef := ProgramUtil.getPathedClassInProgram(inmodel, p) "Look first inside \'inmodel\'" ;
5158 7 cdef := ProgramUtil.getPathedClassInProgram(path, Absyn.PROGRAM({inmodeldef},Absyn.TOP()));
5159 ✗ newpath := AbsynUtil.joinPaths(inmodel, path);
5160 ✗ then
5161 (cdef,newpath);
5162
5163 case (path,inmodel,p) /* Then look inside next level */
5164 algorithm
5165 //fprintln(Flags.INTER, "Interactive.lookupClassdef 2 Looking for: " + AbsynUtil.pathString(path) + " in: " + AbsynUtil.pathString(inmodel));
5166 7 innewpath := AbsynUtil.stripLast(inmodel);
5167 ✗ (cdef,respath) := lookupClassdef(path, innewpath, p);
5168 then
5169 (cdef,respath);
5170
5171 case (path,_,p)
5172 algorithm
5173 //fprintln(Flags.INTER, "Interactive.lookupClassdef 3 Looking for: " + AbsynUtil.pathString(path) + " in: " + AbsynUtil.pathString(inmodel));
5174 7 cdef := ProgramUtil.getPathedClassInProgram(path, p) "Finally look in top level" ;
5175 6 then
5176 (cdef,path);
5177
5178 1 case (Absyn.IDENT(name = "Real"),_,_) then (Absyn.CLASS("Real",false,false,false,Absyn.R_PREDEFINED_REAL(),
5179 Absyn.dummyParts,{},{},{},Absyn.dummyInfo),Absyn.IDENT("Real"));
5180
5181 ✗ case (Absyn.IDENT(name = "Integer"),_,_) then (Absyn.CLASS("Integer",false,false,false,Absyn.R_PREDEFINED_INTEGER(),
5182 Absyn.dummyParts,{},{},{},Absyn.dummyInfo),Absyn.IDENT("Integer"));
5183
5184 ✗ case (Absyn.IDENT(name = "String"),_,_) then (Absyn.CLASS("String",false,false,false,Absyn.R_PREDEFINED_STRING(),
5185 Absyn.dummyParts,{},{},{},Absyn.dummyInfo),Absyn.IDENT("String"));
5186
5187 ✗ case (Absyn.IDENT(name = "Boolean"),_,_) then (Absyn.CLASS("Boolean",false,false,false,Absyn.R_PREDEFINED_BOOLEAN(),
5188 Absyn.dummyParts,{},{},{},Absyn.dummyInfo),Absyn.IDENT("Boolean"));
5189 // BTH
5190 case (Absyn.IDENT(name = "Clock"),_,_)
5191 algorithm
5192 ✗ true := Config.synchronousFeaturesAllowed();
5193 ✗ then (Absyn.CLASS("Clock",false,false,false,Absyn.R_PREDEFINED_CLOCK(),
5194 Absyn.dummyParts,{},{},{},Absyn.dummyInfo),Absyn.IDENT("Clock"));
5195
5196 case (path,inmodel,_)
5197 algorithm
5198 //fprintln(Flags.INTER, "Interactive.lookupClassdef 8 Looking for: " + AbsynUtil.pathString(path) + " in: " + AbsynUtil.pathString(inmodel));
5199 ✗ s1 := AbsynUtil.pathString(path);
5200 ✗ s2 := AbsynUtil.pathString(inmodel);
5201 ✗ Error.addMessage(Error.LOOKUP_ERROR, {s1,s2});
5202 ✗ then
5203 fail();
5204 end matchcontinue;
5205 end lookupClassdef;
5206
5207 protected function deleteOrUpdateComponent
5208 " This function deletes a component from a class given the name of the
5209 component instance, the model in which the component is instantiated in,
5210 and the Program. Both public and protected lists are searched."
5211 input String componentName;
5212 input Absyn.Path classPath;
5213 input output Absyn.Program program;
5214 input Option<tuple<Absyn.Path, Absyn.ComponentItem>> item;
5215 protected
5216 Absyn.Within w;
5217 Absyn.Class cls;
5218 algorithm
5219
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
5 w := if AbsynUtil.pathIsIdent(classPath) then Absyn.Within.TOP() else Absyn.Within.WITHIN(AbsynUtil.stripLast(classPath));
5220 5 cls := ProgramUtil.getPathedClassInProgram(classPath, program);
5221 5 cls := deleteOrUpdateComponentFromClass(componentName, cls, item);
5222 5 program := ProgramUtil.updateProgram(Absyn.PROGRAM({cls}, w), program);
5223 end deleteOrUpdateComponent;
5224
5225 protected function deleteOrUpdateComponentFromClass
5226 " This function deletes a component from a class given
5227 the name of the component instance, and a \'Class\'.
5228 Both public and protected lists are searched."
5229 input String inString;
5230 input Absyn.Class inClass;
5231 input Option<tuple<Absyn.Path,Absyn.ComponentItem>> item;
5232 output Absyn.Class outClass;
5233 algorithm
5234 outClass := match (inString,inClass)
5235 local
5236 list<Absyn.ElementItem> publst,publst2,protlst,protlst2;
5237 Integer l2,l1,l1_1;
5238 list<Absyn.ClassPart> parts2,parts;
5239 String name;
5240 Boolean success;
5241 Option<String> cmt;
5242 Absyn.Ident bcpath;
5243 list<Absyn.ElementArg> mod;
5244 list<String> typeVars;
5245 list<Absyn.NamedArg> classAttrs;
5246 list<Absyn.Annotation> ann;
5247
5248 // Search in public list
5249 case (name,outClass as Absyn.CLASS(
5250 body = Absyn.PARTS(typeVars = typeVars,classAttrs = classAttrs,classParts = parts,ann = ann,comment = cmt),
5251 info = _))
5252 algorithm
5253 5 publst := ProgramUtil.getPublicList(parts);
5254 5 (publst2, success) := deleteOrUpdateComponentFromElementitems(name, publst, item);
5255 5 l2 := listLength(publst2);
5256 5 l1 := listLength(publst);
5257 5 l1_1 := l1 - 1;
5258
5/16
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 5 times.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 5 times.
✗ Branch 15 not taken.
5 if (/*delete case*/(intEq(l1_1, l2) and isNone(item) and success) or
5259 /*update case*/(boolNot(intEq(l1_1, l2)) and isSome(item)) and success) then
5260 5 parts2 := ProgramUtil.replacePublicList(parts, publst2);
5261 else
5262 ✗ protlst := ProgramUtil.getProtectedList(parts);
5263 ✗ protlst2 := deleteOrUpdateComponentFromElementitems(name, protlst, item);
5264 ✗ parts2 := ProgramUtil.replaceProtectedList(parts, protlst2);
5265 end if;
5266 10 outClass.body := Absyn.PARTS(typeVars,classAttrs,parts2,ann,cmt);
5267 then outClass;
5268
5269 // adrpo search also in model extends X end X
5270 case (name,outClass as Absyn.CLASS(
5271 body = Absyn.CLASS_EXTENDS(baseClassName=bcpath, modifications=mod, parts = parts,ann = ann,comment = cmt),
5272 info = _))
5273 algorithm
5274 ✗ publst := ProgramUtil.getPublicList(parts);
5275 ✗ (publst2, success) := deleteOrUpdateComponentFromElementitems(name, publst, item);
5276 ✗ l2 := listLength(publst2);
5277 ✗ l1 := listLength(publst);
5278 ✗ l1_1 := l1 - 1;
5279 ✗ if (/*delete case*/(intEq(l1_1, l2) and isNone(item) and success) or
5280 /*update case*/(boolNot(intEq(l1_1, l2)) and isSome(item)) and success) then
5281 ✗ parts2 := ProgramUtil.replacePublicList(parts, publst2);
5282 else
5283 ✗ protlst := ProgramUtil.getProtectedList(parts);
5284 ✗ protlst2 := deleteOrUpdateComponentFromElementitems(name, protlst, item);
5285 ✗ parts2 := ProgramUtil.replaceProtectedList(parts, protlst2);
5286 end if;
5287 ✗ outClass.body := Absyn.CLASS_EXTENDS(bcpath,mod,cmt,parts2,ann);
5288 then outClass;
5289 end match;
5290 end deleteOrUpdateComponentFromClass;
5291
5292 protected function deleteOrUpdateComponentFromElementitems
5293 "Helper function to deleteOrUpdateComponentFromClass."
5294 input String inString;
5295 input list<Absyn.ElementItem> inAbsynElementItemLst;
5296 input Option<tuple<Absyn.Path,Absyn.ComponentItem>> item;
5297 output list<Absyn.ElementItem> outAbsynElementItemLst;
5298 output Boolean success;
5299 algorithm
5300 (outAbsynElementItemLst, success) := match (inString,inAbsynElementItemLst)
5301 local
5302 String name,name2;
5303 list<Absyn.ElementItem> xs,res;
5304 Absyn.ElementItem x;
5305 Absyn.Element elt, eltold;
5306 list<Absyn.ComponentItem> comps;
5307 Absyn.ComponentItem compitem;
5308 Absyn.ElementSpec spec;
5309 Absyn.Path tppath;
5310 Absyn.TypeSpec typeSpec;
5311 Boolean hasOtherComponents;
5312 Boolean successResult;
5313 case (_,{}) then ({}, false);
5314 case (name,(x as Absyn.ELEMENTITEM(element = elt as Absyn.ELEMENT(specification = spec as Absyn.COMPONENTS(typeSpec = typeSpec as Absyn.TPATH(), components = comps)))) :: xs)
5315 algorithm
5316
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 12 times.
24 if max(match c
5317 case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = name2)) guard stringEq(name, name2) then true;
5318 else false;
5319 end match for c in comps) then
5320 // These components do contain the name we are looking for
5321 (res, successResult) := match item
5322 case SOME((tppath, compitem))
5323 algorithm
5324 // It is an update operation
5325
2/2
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
5 if AbsynUtil.pathEqual(tppath, AbsynUtil.typeSpecPath(spec.typeSpec)) then
5326
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
6 spec.components := list(match c
5327 case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = name2)) guard stringEq(name, name2) then compitem;
5328 else c;
5329 end match for c in comps);
5330 3 elt.specification := spec;
5331 3 res := Absyn.ELEMENTITEM(elt)::xs;
5332 3 successResult := true;
5333 else
5334 eltold := elt;
5335 /* We need to split the old component into two parts: one with the renamed typename */
5336
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 spec.components := list(c for c
5337 guard match c
5338
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = name2)) then not stringEq(name, name2);
5339 else true;
5340 end match in comps);
5341 2 hasOtherComponents := not listEmpty(spec.components);
5342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if hasOtherComponents then
5343 ✗ elt.specification := spec;
5344 eltold := elt;
5345 end if;
5346 2 spec.components := {compitem};
5347 2 typeSpec.path := tppath;
5348 2 spec.typeSpec := typeSpec;
5349 2 elt.specification := spec;
5350 2 res := Absyn.ELEMENTITEM(elt)::xs;
5351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if hasOtherComponents then
5352 ✗ res := Absyn.ELEMENTITEM(eltold)::res;
5353 end if;
5354 2 successResult := true;
5355 end if;
5356 5 then (res, successResult);
5357 else
5358 algorithm
5359 // It is a deletion
5360
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if listLength(comps)==1 then
5361 res := xs;
5362 4 successResult := true;
5363 else
5364 ✗ spec.components := list(c for c
5365 guard match c
5366 ✗ case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = name2)) then not stringEq(name, name2);
5367 else true;
5368 end match in comps);
5369 ✗ elt.specification := spec;
5370 ✗ res := Absyn.ELEMENTITEM(elt)::xs;
5371 ✗ successResult := true;
5372 end if;
5373 4 then (res, successResult);
5374 end match;
5375 else
5376 3 (res, successResult) := deleteOrUpdateComponentFromElementitems(name, xs, item);
5377 res := x :: res;
5378 end if;
5379 12 then (res, successResult);
5380 case (name,(x :: xs))
5381 algorithm
5382 // Did not find the name we are looking for in element x
5383 ✗ (res, successResult) := deleteOrUpdateComponentFromElementitems(name, xs, item);
5384 ✗ then ((x :: res), successResult);
5385 end match;
5386 end deleteOrUpdateComponentFromElementitems;
5387
5388 public function addComponent
5389 "Adds a component to the program."
5390 input String componentName;
5391 input Absyn.Path typeName;
5392 input Absyn.Path classPath;
5393 input Absyn.Exp bindingExp;
5394 input Absyn.Modification modifier;
5395 input Absyn.Exp commentExp;
5396 input Absyn.Exp annotationExp;
5397 input output Absyn.Program program;
5398 output Boolean success = true;
5399 protected
5400 String filename;
5401 Absyn.Class cdef;
5402 Option<Absyn.Comment> annotation_;
5403 Option<Absyn.Modification> modification;
5404 Absyn.Within w;
5405 Absyn.InnerOuter io;
5406 Option<Absyn.RedeclareKeywords> redecl;
5407 Absyn.ElementAttributes attr;
5408 SourceInfo info;
5409 Absyn.Path ty_path;
5410 algorithm
5411 try
5412 w := match classPath
5413 case Absyn.IDENT() then Absyn.TOP();
5414 4 else Absyn.WITHIN(AbsynUtil.stripLast(classPath));
5415 end match;
5416
5417 18 cdef as Absyn.CLASS(info=SOURCEINFO(fileName=filename)) :=
5418 ProgramUtil.getPathedClassInProgram(classPath, program);
5419 18 info := SOURCEINFO(filename, false, 0, 0, 0, 0, 0.0);
5420
5421 18 annotation_ := InteractiveUtil.makeCommentFromArgs(commentExp, annotationExp);
5422 18 modification := InteractiveUtil.makeModifierFromArgs(bindingExp, modifier, info);
5423 18 (io, redecl, attr) := getDefaultPrefixes(program, typeName);
5424
5425
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
18 SOME(ty_path) := AbsynUtil.pathStripSamePrefix(typeName, classPath);
5426
5427
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if AbsynUtil.pathContains(classPath, AbsynUtil.pathFirstIdent(ty_path)) then
5428 // Keep the full type name if the first identifier of the stripped name
5429 // is part of the class path, to avoid name collisions.
5430 ty_path := typeName;
5431 end if;
5432
5433 36 cdef := InteractiveUtil.addToPublic(cdef,
5434 Absyn.ELEMENTITEM(
5435 Absyn.ELEMENT(false, redecl, io,
5436 Absyn.COMPONENTS(attr, Absyn.TPATH(ty_path, NONE()),
5437 {Absyn.COMPONENTITEM(Absyn.COMPONENT(componentName, {}, modification), NONE(), annotation_)}),
5438 info, NONE())
5439 )
5440 );
5441 18 program := ProgramUtil.updateProgram(Absyn.PROGRAM({cdef}, w), program);
5442 else
5443 success := false;
5444 end try;
5445 end addComponent;
5446
5447 protected function getDefaultPrefixes "Retrieves default prefixes by looking at the defaultComponentPrefixes annotation"
5448 input Absyn.Program p;
5449 input Absyn.Path className;
5450 output Absyn.InnerOuter io;
5451 output Option<Absyn.RedeclareKeywords> redecl;
5452 output Absyn.ElementAttributes attr;
5453 algorithm
5454 (io,redecl,attr) := match className
5455 local String str;
5456 case _ algorithm
5457 18 str := ProgramUtil.getNamedAnnotationExp(className,p,Absyn.IDENT("defaultComponentPrefixes"),SOME("{}"),ProgramUtil.getDefaultComponentPrefixesModStr);
5458 18 io := getDefaultInnerOuter(str);
5459 18 redecl := getDefaultReplaceable(str);
5460 18 redecl := makeReplaceableIfPartial(p, className, redecl);
5461 18 attr := getDefaultAttr(str);
5462 then(io,redecl,attr);
5463 end match;
5464 end getDefaultPrefixes;
5465
5466 protected function makeReplaceableIfPartial
5467 "This function takes:
5468 arg1 - a Program,
5469 arg2 - the path of class,
5470 arg3 - redeclare option.
5471 The result is an updated redeclare option.
5472 This function checks if the class is partial or not, if yes then it adds the replaceable keyword to the component."
5473 input Absyn.Program p;
5474 input Absyn.Path className;
5475 input Option<Absyn.RedeclareKeywords> redecl;
5476 output Option<Absyn.RedeclareKeywords> new_redecl;
5477 algorithm
5478 new_redecl := match redecl
5479 case NONE() guard isPartial(className, p)
5480 then SOME(Absyn.REPLACEABLE());
5481 /* if the above case fails i.e class is not partial */
5482 case NONE()
5483 then redecl;
5484 case SOME(Absyn.REPLACEABLE())
5485 then redecl;
5486 end match;
5487 end makeReplaceableIfPartial;
5488
5489 protected function getDefaultInnerOuter "helper function to getDefaultPrefixes"
5490 input String str;
5491 output Absyn.InnerOuter io;
5492 algorithm
5493 io := matchcontinue str
5494 case _ algorithm
5495
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 16 times.
18 -1 := System.stringFind(str,"inner");
5496
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 15 times.
16 -1 := System.stringFind(str,"outer");
5497 then Absyn.NOT_INNER_OUTER();
5498
5499 case _ algorithm
5500
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
3 -1 := System.stringFind(str,"outer");
5501 then Absyn.INNER();
5502
5503 case _ algorithm
5504
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 -1 := System.stringFind(str,"inner");
5505 then Absyn.OUTER();
5506 end matchcontinue;
5507 end getDefaultInnerOuter;
5508
5509 protected function getDefaultReplaceable "helper function to getDefaultPrefixes"
5510 input String str;
5511 output Option<Absyn.RedeclareKeywords> repl;
5512 algorithm
5513 repl := matchcontinue str
5514 case _ algorithm
5515
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 17 times.
18 -1 := System.stringFind(str,"replaceable");
5516 then NONE();
5517 case _ algorithm
5518
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
1 failure(-1 := System.stringFind(str,"replaceable"));
5519 then SOME(Absyn.REPLACEABLE());
5520 end matchcontinue;
5521 end getDefaultReplaceable;
5522
5523 protected function getDefaultAttr "helper function to getDefaultPrefixes"
5524 input String str;
5525 output Absyn.ElementAttributes attr;
5526 algorithm
5527 attr := matchcontinue str
5528 case _ algorithm
5529
3/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 17 times.
18 failure(-1 := System.stringFind(str,"parameter"));
5530 then Absyn.ATTR(false,false,Absyn.NON_PARALLEL(),Absyn.PARAM(),Absyn.BIDIR(),Absyn.NONFIELD(),{});
5531
5532 case _ algorithm
5533
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
17 failure(-1 := System.stringFind(str,"constant"));
5534 then Absyn.ATTR(false,false,Absyn.NON_PARALLEL(),Absyn.CONST(),Absyn.BIDIR(),Absyn.NONFIELD(),{});
5535
5536 case _ algorithm
5537
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
17 failure(-1 := System.stringFind(str,"discrete"));
5538 then Absyn.ATTR(false,false,Absyn.NON_PARALLEL(),Absyn.DISCRETE(),Absyn.BIDIR(),Absyn.NONFIELD(),{});
5539 case _ then Absyn.ATTR(false,false,Absyn.NON_PARALLEL(),Absyn.VAR(),Absyn.BIDIR(),Absyn.NONFIELD(),{});
5540 end matchcontinue;
5541 end getDefaultAttr;
5542
5543
5544
5545 public function updateComponent
5546 " This function updates a component in a class. The reason for having
5547 thisfunction is that a deletion followed by an addition would mean that
5548 all optional arguments must be present to the add_componentfunction
5549 in order to get the same component attributes,etc. as previous."
5550 input String componentName;
5551 input Absyn.Path typeName;
5552 input Absyn.Path classPath;
5553 input Absyn.Exp bindingExp;
5554 input Absyn.Modification modifier;
5555 input Absyn.Exp commentExp;
5556 input Absyn.Exp annotationExp;
5557 input output Absyn.Program program;
5558 output Boolean success = true;
5559 protected
5560 list<Absyn.ClassPart> parts;
5561 list<Absyn.ElementItem> publst, protlst;
5562 list<Absyn.ComponentItem> items;
5563 Absyn.ArrayDim arrayDimensions;
5564 Option<Absyn.Modification> mod, modification;
5565 Option<Absyn.Exp> cond;
5566 Option<Absyn.Comment> ann, annotation_;
5567 algorithm
5568 try
5569
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) := ProgramUtil.getPathedClassInProgram(classPath, program);
5570 5 publst := ProgramUtil.getPublicList(parts);
5571 5 protlst := ProgramUtil.getProtectedList(parts);
5572
3/6
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
5 Absyn.ELEMENT(_,_,_,Absyn.COMPONENTS(_,Absyn.TPATH(_,_),items),_,_) := getElementContainsName(Absyn.CREF_IDENT(componentName,{}), listAppend(publst, protlst));
5573 5 Absyn.COMPONENTITEM(Absyn.COMPONENT(_,arrayDimensions,mod),cond,ann) := getCompitemNamed(Absyn.CREF_IDENT(componentName,{}), items);
5574 5 annotation_ := InteractiveUtil.makeCommentFromArgs(commentExp, annotationExp, ann);
5575 5 modification := InteractiveUtil.makeModifierFromArgs(bindingExp, modifier, Absyn.dummyInfo, mod);
5576 10 program := deleteOrUpdateComponent(componentName, classPath, program, SOME((typeName, Absyn.COMPONENTITEM(Absyn.COMPONENT(componentName,arrayDimensions,modification),cond,annotation_))));
5577 else
5578 success := false;
5579 /* adrpo: TODO!: handle also model extends M end M; i.e. CLASS_EXTENDS */
5580 end try;
5581 end updateComponent;
5582
5583 public function deleteComponent
5584 "Deletes a component from the program."
5585 input String componentName;
5586 input Absyn.Path classPath;
5587 input output Absyn.Program program;
5588 output Boolean success = true;
5589 algorithm
5590 try
5591 ✗ program := deleteOrUpdateComponent(componentName, classPath, program, NONE());
5592 else
5593 success := false;
5594 end try;
5595 end deleteComponent;
5596
5597 public function addClassAnnotation
5598 "Adds an annotation to the referenced class."
5599 input Absyn.ComponentRef inClass;
5600 input list<Absyn.NamedArg> inAnnotation;
5601 input Absyn.Program inProgram;
5602 output Absyn.Program outProgram;
5603 protected
5604 Absyn.Path class_path;
5605 Absyn.Class cls;
5606 Absyn.Within class_within;
5607 algorithm
5608 8 class_path := AbsynUtil.crefToPath(inClass);
5609 8 cls := ProgramUtil.getPathedClassInProgram(class_path, inProgram);
5610 8 cls := addClassAnnotationToClass(cls, InteractiveUtil.annotationListToAbsyn(inAnnotation));
5611
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 class_within := if AbsynUtil.pathIsIdent(class_path) then
5612 Absyn.TOP() else Absyn.WITHIN(AbsynUtil.stripLast(class_path));
5613 8 outProgram := ProgramUtil.updateProgram(Absyn.PROGRAM({cls}, class_within), inProgram);
5614 end addClassAnnotation;
5615
5616 public function addClassAnnotationToClass
5617 "Adds an annotation to a given class."
5618 input Absyn.Class inClass;
5619 input Absyn.Annotation inAnnotation;
5620 output Absyn.Class outClass;
5621 protected
5622 Absyn.ClassDef body;
5623 algorithm
5624
1/7
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
8 Absyn.CLASS(body = body) := inClass;
5625
5626 body := match body
5627 case Absyn.PARTS()
5628 algorithm
5629 16 body.ann := {AbsynUtil.mergeAnnotationsList(inAnnotation, body.ann)};
5630 then
5631 body;
5632
5633 case Absyn.DERIVED()
5634 algorithm
5635 ✗ body.comment := AbsynUtil.mergeCommentAnnotation(inAnnotation, body.comment);
5636 then
5637 body;
5638
5639 case Absyn.ENUMERATION()
5640 algorithm
5641 ✗ body.comment := AbsynUtil.mergeCommentAnnotation(inAnnotation, body.comment);
5642 then
5643 body;
5644
5645 case Absyn.OVERLOAD()
5646 algorithm
5647 ✗ body.comment := AbsynUtil.mergeCommentAnnotation(inAnnotation, body.comment);
5648 then
5649 body;
5650
5651 case Absyn.CLASS_EXTENDS()
5652 algorithm
5653 ✗ body.ann := {AbsynUtil.mergeAnnotationsList(inAnnotation, body.ann)};
5654 then
5655 body;
5656
5657 case Absyn.PDER()
5658 algorithm
5659 ✗ body.comment := AbsynUtil.mergeCommentAnnotation(inAnnotation, body.comment);
5660 then
5661 body;
5662 end match;
5663
5664 8 outClass := AbsynUtil.setClassBody(inClass, body);
5665 end addClassAnnotationToClass;
5666
5667 protected function getInheritedClassesHelper
5668 "Helper function to getInheritedClasses."
5669 input SCode.Element inClass1;
5670 input Absyn.Class inClass2;
5671 input FCore.Graph inEnv4;
5672 output list<Absyn.Path> outAbsynComponentRefLst;
5673 algorithm
5674 outAbsynComponentRefLst := matchcontinue (inClass1,inClass2,inEnv4)
5675 local
5676 list<Absyn.Path> lst;
5677 String id;
5678 SCode.Element c;
5679 Absyn.Class cdef;
5680 FCore.Graph env,env2,env_2;
5681 ClassInf.State ci_state;
5682 SCode.Encapsulated encflag;
5683 SCode.Restriction restr;
5684
5685 case ((c as SCode.CLASS(name = id,encapsulatedPrefix = encflag,restriction = restr)),cdef,env)
5686 algorithm
5687 ✗ ErrorExt.setCheckpoint("getInheritedClassesHelper");
5688 ✗ if SCodeUtil.isDerivedClass(c) then
5689 // for derived classes search in the parent
5690 ✗ env_2 := env;
5691 else
5692 // for non-derived classes search from self
5693 ✗ env2 := FGraph.openScope(env, encflag, id, FGraph.restrictionToScopeType(restr));
5694 ✗ ci_state := ClassInfUtil.start(restr, FGraph.getGraphName(env2));
5695 ✗ (_,env_2,_,_,_) :=
5696 Inst.partialInstClassIn(FCore.emptyCache(),env2,InnerOuter.emptyInstHierarchy,
5697 DAE.NOMOD(), DAE.NOPRE(), ci_state, c, SCode.PUBLIC(), {}, 0);
5698 end if;
5699 ✗ lst := getBaseClasses(cdef, env_2);
5700 ✗ ErrorExt.rollBack("getInheritedClassesHelper");
5701 then
5702 lst;
5703
5704 // clear any messages that may have been added
5705 case ((SCode.CLASS()),_,_)
5706 algorithm
5707 ✗ ErrorExt.rollBack("getInheritedClassesHelper");
5708 ✗ then
5709 fail();
5710
5711 end matchcontinue;
5712 end getInheritedClassesHelper;
5713
5714 public function getInheritedClasses
5715 input Absyn.Path inPath;
5716 output list<Absyn.Path> outPaths;
5717 algorithm
5718
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 if Flags.isSet(Flags.NF_API) then
5719 7 outPaths := NFApi.getInheritedClasses(inPath, SymbolTable.getAbsyn());
5720 7 return;
5721 end if;
5722
5723 try
5724
5725 ✗ if not Flags.isSet(Flags.NF_API_NOISE) then
5726 ✗ ErrorExt.setCheckpoint("getInheritedClasses");
5727 end if;
5728
5729 outPaths := matchcontinue inPath
5730 local
5731 Absyn.Path modelpath;
5732 Absyn.Class cdef;
5733 list<SCode.Element> p_1;
5734 FCore.Graph env,env_1;
5735 SCode.Element c;
5736 list<Absyn.ElementSpec> extendsLst;
5737 FCore.Cache cache;
5738 list<Absyn.Path> paths;
5739
5740 case modelpath
5741 algorithm
5742 ✗ cdef := ProgramUtil.getPathedClassInProgram(modelpath, SymbolTable.getAbsyn());
5743 ✗ p_1 := SymbolTable.getSCode();
5744 ✗ (cache,env) := Inst.makeEnvFromProgram(p_1);
5745 ✗ (_,(c as SCode.CLASS()),env_1) := Lookup.lookupClass(cache,env, modelpath);
5746 ✗ paths := getInheritedClassesHelper(c, cdef, env_1);
5747 ✗ failure({} := paths);
5748 ✗ then
5749 paths;
5750 case modelpath /* if above fails, baseclass not defined. return its name */
5751 algorithm
5752 ✗ cdef := ProgramUtil.getPathedClassInProgram(modelpath, SymbolTable.getAbsyn());
5753 ✗ extendsLst := getExtendsInClass(cdef);
5754 ✗ paths := List.map(extendsLst, AbsynUtil.elementSpecToPath);
5755 then
5756 paths;
5757 else {};
5758 end matchcontinue;
5759
5760 ✗ if not Flags.isSet(Flags.NF_API_NOISE) then
5761 ✗ ErrorExt.rollBack("getInheritedClasses");
5762 end if;
5763
5764 else
5765 ✗ if not Flags.isSet(Flags.NF_API_NOISE) then
5766 ✗ ErrorExt.rollBack("getInheritedClasses");
5767 end if;
5768 end try;
5769
5770 end getInheritedClasses;
5771
5772 public function getInheritanceCount
5773 "This function takes a Path and a Program and
5774 returns the number of inherited classes in the class
5775 referenced by the Path."
5776 input Absyn.Path classPath;
5777 input Absyn.Program program;
5778 output Values.Value result;
5779 protected
5780 Absyn.Class cls;
5781 algorithm
5782 try
5783 2 cls := ProgramUtil.getPathedClassInProgram(classPath, program);
5784 2 result := ValuesMake.makeInteger(countBaseClasses(cls));
5785 else
5786 ✗ result := ValuesMake.makeInteger(0);
5787 end try;
5788 end getInheritanceCount;
5789
5790 protected function getNthInheritedClassAnnotationOpt
5791 "This function takes a ComponentRef, an integer and a Program and returns
5792 the ANNOTATION on the extends of the nth inherited class in the class referenced by the modelpath."
5793 input Absyn.Path inModelPath;
5794 input Integer inInteger;
5795 input Absyn.Class inClass;
5796 input Absyn.Program inProgram;
5797 output String outString;
5798 output Option<Absyn.Annotation> annotationOpt;
5799 algorithm
5800 (outString, annotationOpt) := matchcontinue inInteger
5801 local
5802 Absyn.Path path;
5803 Absyn.Class cdef;
5804 String s;
5805 Integer n;
5806 list<Absyn.ElementSpec> extends_;
5807 Option<Absyn.Annotation> annOpt;
5808
5809 /* adrpo: fixme, handle this case too!
5810 case (modelpath,n,inClass,p)
5811 algorithm
5812 cdef = inClass;
5813 p_1 = AbsynToSCode.translateAbsyn2SCode(p);
5814 (cache,env) = Inst.makeEnvFromProgram(p_1);
5815 (_,(c as SCode.CLASS(id,_,encflag,restr,_)),env_1) = Lookup.lookupClass(cache, env, modelpath);
5816 str = getNthInheritedClass2(c, cdef, n, env_1);
5817 then
5818 (str, annOpt);
5819 */
5820
5821 case n /* if above fails, baseclass not defined. return its name */
5822 algorithm
5823 cdef := inClass;
5824 ✗ extends_ := getExtendsInClass(cdef);
5825 ✗ Absyn.EXTENDS(path,_,annOpt) := listGet(extends_, n);
5826 ✗ s := AbsynUtil.pathString(path);
5827 then
5828 (s, annOpt);
5829
5830 else ("Error", NONE());
5831 end matchcontinue;
5832 end getNthInheritedClassAnnotationOpt;
5833
5834 protected function getMapAnnotationStr
5835 "function: getMapAnnotationStr"
5836 input list<Absyn.ElementArg> inAbsynElementArgLst;
5837 input String inMapType "IconMap or DiagramMap";
5838 input Absyn.Class inClass;
5839 input Absyn.Program inFullProgram;
5840 input Absyn.Path inModelPath;
5841 output String outString;
5842 algorithm
5843 outString := matchcontinue inAbsynElementArgLst
5844 local
5845 String str;
5846 Absyn.ElementArg ann;
5847 list<Absyn.ElementArg> xs;
5848 String mapType;
5849
5850 case {} then "{}";
5851
5852 case (ann as Absyn.MODIFICATION(path = Absyn.IDENT(name = mapType))) :: _
5853 algorithm
5854 // make sure is the given type: IconMap or DiagramMap
5855 ✗ true := stringEqual(mapType, inMapType);
5856 ✗ str := getAnnotationString(Absyn.ANNOTATION({ann}), inClass, inFullProgram, inModelPath);
5857 then
5858 str;
5859
5860 case _ :: xs
5861 algorithm
5862 ✗ str := getMapAnnotationStr(xs, inMapType, inClass, inFullProgram, inModelPath);
5863 then
5864 str;
5865 end matchcontinue;
5866 end getMapAnnotationStr;
5867
5868 public function getNthInheritedClassIconMapAnnotation
5869 input Absyn.Path classPath;
5870 input Integer n;
5871 input Absyn.Program program;
5872 output Values.Value result;
5873 protected
5874 function impl
5875 input Absyn.Path classPath;
5876 input Integer n;
5877 input Absyn.Program program;
5878 input Access accessLevel;
5879 output Values.Value result;
5880 algorithm
5881 ✗ result := getNthInheritedClassMapAnnotation(classPath, n, program, "IconMap");
5882 end impl;
5883 algorithm
5884 ✗ result := InteractiveUtil.accessClass(classPath, program, function impl(n = n), evaluateParams = true);
5885 end getNthInheritedClassIconMapAnnotation;
5886
5887 public function getNthInheritedClassDiagramMapAnnotation
5888 input Absyn.Path classPath;
5889 input Integer n;
5890 input Absyn.Program program;
5891 output Values.Value result;
5892 protected
5893 function impl
5894 input Absyn.Path classPath;
5895 input Integer n;
5896 input Absyn.Program program;
5897 input Access accessLevel;
5898 output Values.Value result;
5899 algorithm
5900 ✗ result := getNthInheritedClassMapAnnotation(classPath, n, program, "DiagramMap");
5901 end impl;
5902 algorithm
5903 ✗ result := InteractiveUtil.accessClass(classPath, program, function impl(n = n), evaluateParams = true);
5904 end getNthInheritedClassDiagramMapAnnotation;
5905
5906 protected function getNthInheritedClassMapAnnotation
5907 "This function takes a Path, an integer and a Program and returns
5908 the ANNOTATION on the extends of the nth inherited class in the class referenced by the ComponentRef."
5909 input Absyn.Path classPath;
5910 input Integer n;
5911 input Absyn.Program program;
5912 input String mapType "IconMap or DiagramMap";
5913 output Values.Value result;
5914 protected
5915 Absyn.Class cls;
5916 String s, annStr;
5917 Option<Absyn.Annotation> opt_ann;
5918 list<Absyn.ElementArg> args;
5919 algorithm
5920 ✗ cls := ProgramUtil.getPathedClassInProgram(classPath, program);
5921 ✗ (s, opt_ann) := getNthInheritedClassAnnotationOpt(classPath, n, cls, program);
5922
5923 annStr := match opt_ann
5924 ✗ case SOME(Absyn.ANNOTATION(args)) then getMapAnnotationStr(args, mapType, cls, program, classPath);
5925 else "{}";
5926 end match;
5927
5928 ✗ result := InteractiveUtil.makeAnnotationArrayValue({s, annStr});
5929 end getNthInheritedClassMapAnnotation;
5930
5931 protected function getExtendsInClass
5932 "Returns all ElementSpec of EXTENDS in a class."
5933 input Absyn.Class inClass;
5934 output list<Absyn.ElementSpec> outExtends;
5935 protected
5936 list<Absyn.ClassPart> parts;
5937 algorithm
5938 outExtends := match inClass
5939 ✗ case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) then getExtendsInParts(parts);
5940 /* adrpo: TODO! how about model extends M(modifications) end M??
5941 should we report EXTENDS(IDENT(M), modifications)? */
5942 ✗ case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) then getExtendsInParts(parts);
5943 else {};
5944 end match;
5945 end getExtendsInClass;
5946
5947 protected function getExtendsInParts
5948 input list<Absyn.ClassPart> parts;
5949 output list<Absyn.ElementSpec> outExtends = {};
5950 protected
5951 Absyn.ElementSpec spec;
5952 algorithm
5953 ✗ for part in parts loop
5954 ✗ for el in AbsynUtil.getElementItemsInClassPart(part) loop
5955 outExtends := match el
5956 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = spec as Absyn.EXTENDS()))
5957 then spec :: outExtends;
5958 else outExtends;
5959 end match;
5960 end for;
5961 end for;
5962
5963 ✗ outExtends := Dangerous.listReverseInPlace(outExtends);
5964 end getExtendsInParts;
5965
5966 public function getComponentCount
5967 " This function takes a ComponentRef and a Program and returns the
5968 number of public components in the class referenced by the ComponentRef."
5969 input Absyn.Path model_;
5970 input Absyn.Program p;
5971 output Integer count;
5972 protected
5973 Absyn.Class cdef;
5974 algorithm
5975 5 cdef := ProgramUtil.getPathedClassInProgram(model_, p);
5976 5 count := countComponents(cdef);
5977 end getComponentCount;
5978
5979 protected function countComponents
5980 " This function takes a Class and returns the
5981 number of components in that class"
5982 input Absyn.Class inClass;
5983 output Integer outInteger;
5984 algorithm
5985 outInteger := matchcontinue inClass
5986 local
5987 Integer c1,c2,res;
5988 list<Absyn.ElementItem> elt;
5989 list<Absyn.ClassPart> lst;
5990 Option<String> cmt;
5991 list<Absyn.Annotation> ann;
5992 Absyn.Class cdef;
5993
5994 // a class with parts
5995 case cdef as Absyn.CLASS(
5996 body = Absyn.PARTS(classParts = (Absyn.PUBLIC(contents = elt) :: lst),ann = ann,comment = cmt))
5997 algorithm
5998 10 cdef.body := Absyn.PARTS({},{},lst,ann,cmt);
5999 5 c1 := countComponents(cdef);
6000 5 c2 := countComponentsInElts(elt, 0);
6001 5 then
6002 c1 + c2;
6003
6004 case cdef as Absyn.CLASS(
6005 body = Absyn.PARTS(classParts = (Absyn.PROTECTED(contents = elt) :: lst),ann = ann,comment = cmt))
6006 algorithm
6007 ✗ cdef.body := Absyn.PARTS({},{},lst,ann,cmt);
6008 ✗ c1 := countComponents(cdef);
6009 ✗ c2 := countComponentsInElts(elt, 0);
6010 ✗ then
6011 c1 + c2;
6012
6013 case cdef as Absyn.CLASS(
6014 body = Absyn.PARTS(classParts = (_ :: lst),ann = ann,comment = cmt))
6015 algorithm
6016 ✗ cdef.body := Absyn.PARTS({},{},lst,ann,cmt);
6017 ✗ res := countComponents(cdef);
6018 then
6019 res;
6020
6021 case Absyn.CLASS(body = Absyn.PARTS(classParts = {})) then 0;
6022
6023 // adrpo: handle also an extended class with parts: model extends M end M;
6024 case cdef as Absyn.CLASS(
6025 body = Absyn.CLASS_EXTENDS(parts = (Absyn.PUBLIC(contents = elt) :: lst),ann = ann,comment = cmt))
6026 algorithm
6027 ✗ cdef.body := Absyn.PARTS({},{},lst,ann,cmt);
6028 ✗ c1 := countComponents(cdef);
6029 ✗ c2 := countComponentsInElts(elt, 0);
6030 ✗ then
6031 c1 + c2;
6032
6033 case cdef as Absyn.CLASS(
6034 body = Absyn.CLASS_EXTENDS(parts = (Absyn.PROTECTED(contents = elt) :: lst),ann=ann,comment = cmt))
6035 algorithm
6036 ✗ cdef.body := Absyn.PARTS({},{},lst,ann,cmt);
6037 ✗ c1 := countComponents(cdef);
6038 ✗ c2 := countComponentsInElts(elt, 0);
6039 ✗ then
6040 c1 + c2;
6041
6042 case cdef as Absyn.CLASS(
6043 body = Absyn.CLASS_EXTENDS(parts = (_ :: lst),ann = ann,comment = cmt))
6044 algorithm
6045 ✗ cdef.body := Absyn.PARTS({},{},lst,ann,cmt);
6046 ✗ res := countComponents(cdef);
6047 then
6048 res;
6049
6050 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = {})) then 0;
6051
6052 // a derived class
6053 case Absyn.CLASS(body = Absyn.DERIVED()) then -1;
6054
6055 end matchcontinue;
6056 end countComponents;
6057
6058 protected function countComponentsInElts
6059 "Helper function to countComponents"
6060 input list<Absyn.ElementItem> inAbsynElementItemLst;
6061 input Integer inInteger;
6062 output Integer outInteger;
6063 algorithm
6064 outInteger:=
6065 match inAbsynElementItemLst
6066 local
6067 list<Absyn.ComponentItem> complst;
6068 list<Absyn.ElementItem> lst;
6069 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.COMPONENTS(components = complst))) :: lst
6070 7 then
6071 countComponentsInElts(lst, inInteger + listLength(complst));
6072 case _ :: lst
6073 1 then
6074 countComponentsInElts(lst, inInteger);
6075 case {} then inInteger;
6076 end match;
6077 end countComponentsInElts;
6078
6079 public function getNthComponent
6080 "This function takes a class path, a program, and an int and returns the name,
6081 type and comment of that component."
6082 input Absyn.Path classPath;
6083 input Absyn.Program program;
6084 input Integer n;
6085 output Values.Value result;
6086 protected
6087 GraphicEnvCache genv;
6088 Absyn.Class cdef;
6089 algorithm
6090 try
6091 4 genv := InteractiveUtil.createEnvironment(SymbolTable.getAbsyn(), SOME(SymbolTable.getSCode()), classPath);
6092 2 cdef := ProgramUtil.getPathedClassInProgram(classPath, program);
6093 2 result := getNthComponent2(cdef, n, genv);
6094 else
6095 ✗ result := ValuesMake.makeBoolean(false);
6096 end try;
6097 end getNthComponent;
6098
6099 protected function getNthComponent2
6100 "Helper function to getNthComponent."
6101 input Absyn.Class inClass;
6102 input Integer n;
6103 input GraphicEnvCache genv;
6104 output Values.Value result;
6105 protected
6106 Absyn.Element comp;
6107 String comp_name, cmt;
6108 Absyn.Path ty;
6109 algorithm
6110 2 comp := InteractiveUtil.getNthComponentInClass(inClass, n);
6111 2 (comp_name, ty, cmt) := getComponentInfoOld(comp, genv);
6112
6113 6 result := Values.ARRAY({
6114 ValuesMake.makeCodeTypeName(ty),
6115 Values.CODE(Absyn.CodeNode.C_VARIABLENAME(Absyn.ComponentRef.CREF_IDENT(comp_name, {}))),
6116 ValuesMake.makeString(cmt)
6117 }, {3});
6118 end getNthComponent2;
6119
6120 protected function useQuotes
6121 input list<Absyn.NamedArg> inAbsynNamedArgLst;
6122 output Boolean outBoolean;
6123 algorithm
6124 outBoolean := match inAbsynNamedArgLst
6125 local
6126 list<Absyn.NamedArg> al;
6127 Boolean b,res;
6128 case {} then false;
6129 case Absyn.NAMEDARG(argName = "useQuotes",argValue = Absyn.BOOL(value = b)) :: _ then b;
6130 case _ :: al
6131 algorithm
6132 ✗ res := useQuotes(al);
6133 then
6134 res;
6135 end match;
6136 end useQuotes;
6137
6138 public function insertQuotesToList
6139 input list<String> inStringList;
6140 output list<String> outStringList;
6141 algorithm
6142 outStringList := match inStringList
6143 local
6144 list<String> res,rest;
6145 String str_1,str;
6146 case {} then {};
6147 case str :: rest
6148 algorithm
6149 4 str_1 := stringAppendList({"\"",str,"\""});
6150 4 res := insertQuotesToList(rest);
6151 then
6152 (str_1 :: res);
6153 end match;
6154 end insertQuotesToList;
6155
6156 public function getComponents
6157 input Absyn.Path classPath;
6158 input Boolean useQuotes;
6159 input Absyn.Program program;
6160 output Values.Value result;
6161 algorithm
6162 20 result := getElements(classPath, useQuotes, program, onlyComponents = true);
6163 end getComponents;
6164
6165 public function getElements
6166 input Absyn.Path classPath;
6167 input Boolean useQuotes;
6168 input Absyn.Program program;
6169 input Boolean onlyComponents = false;
6170 output Values.Value result;
6171 protected
6172 Access access;
6173 Absyn.Class cls;
6174 Interactive.GraphicEnvCache env;
6175 Boolean silent = false;
6176 list<Values.Value> infos = {};
6177 list<Absyn.Element> elems;
6178 algorithm
6179 try
6180 22 access := checkAccessAnnotationAndEncryption(classPath, program);
6181
6182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if access < Access.icon then // Access.icon
6183 ✗ Error.addMessage(Error.ACCESS_ENCRYPTED_PROTECTED_CONTENTS, {});
6184 ✗ result := ValuesMake.makeArray({});
6185 ✗ return;
6186 end if;
6187
6188 22 silent := not Flags.isSet(Flags.NF_API_NOISE);
6189
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if silent then
6190 22 ErrorExt.setCheckpoint(getInstanceName());
6191 end if;
6192
6193 22 cls := ProgramUtil.getPathedClassInProgram(classPath, program);
6194 44 env := InteractiveUtil.createEnvironment(program, SOME(SymbolTable.getSCode()), classPath);
6195
6196
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if access >= Access.diagram then // Access.diagram
6197 22 elems := InteractiveUtil.getProtectedElementsInClass(cls);
6198 22 infos := InteractiveUtil.getElementsInfo(elems, false, useQuotes, onlyComponents, env);
6199 end if;
6200
6201 22 elems := InteractiveUtil.getPublicElementsInClass(cls);
6202 22 infos := InteractiveUtil.getElementsInfo(elems, true, useQuotes, onlyComponents, env, infos);
6203
6204 22 result := ValuesMake.makeArray(infos);
6205 else
6206 ✗ result := ValuesMake.makeArray({});
6207 end try;
6208
6209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if silent then
6210 22 ErrorExt.rollBack(getInstanceName());
6211 end if;
6212 end getElements;
6213
6214 public function getComponentAnnotations " This function takes a `Path\', a `Program\' and
6215 returns a list of all component annotations, as returned by
6216 get_nth_component_annotation.
6217 Both public and protected components are returned, but they need to
6218 be in the same order as get_componentsfunctions, i.e. first public
6219 components then protected ones."
6220 input Absyn.Path classPath;
6221 input Absyn.Program program;
6222 output Values.Value result;
6223 protected
6224 function impl
6225 input Absyn.Path classPath;
6226 input Absyn.Program program;
6227 input Access accessLevel;
6228 output Values.Value result;
6229 protected
6230 Absyn.Class cdef;
6231 list<Absyn.Element> comps = {};
6232
6233 algorithm
6234 5 cdef := ProgramUtil.getPathedClassInProgram(classPath, program);
6235
6236
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if accessLevel >= Access.diagram then
6237 5 comps := InteractiveUtil.getProtectedComponentsInClass(cdef);
6238 end if;
6239
6240 5 comps := listAppend(InteractiveUtil.getPublicComponentsInClass(cdef), comps);
6241 5 result := InteractiveUtil.getElementAnnotationsFromElts(comps, cdef, program, classPath);
6242 end impl;
6243 algorithm
6244 5 result := InteractiveUtil.accessClass(classPath, program, impl, evaluateParams = true);
6245 end getComponentAnnotations;
6246
6247 public function getElementAnnotations " This function takes a `Path\', a `Program\' and
6248 returns a list of all element annotations.
6249 Both public and protected components are returned, but they need to
6250 be in the same order as get_componentsfunctions, i.e. first public
6251 components then protected ones."
6252 input Absyn.Path classPath;
6253 input Absyn.Program program;
6254 output Values.Value result;
6255 protected
6256 function impl
6257 input Absyn.Path classPath;
6258 input Absyn.Program program;
6259 input Access accessLevel;
6260 output Values.Value result;
6261 protected
6262 Absyn.Class cdef;
6263 list<Absyn.Element> elts = {};
6264 algorithm
6265 2 cdef := ProgramUtil.getPathedClassInProgram(classPath, program);
6266
6267
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if accessLevel >= Access.diagram then
6268 2 elts := InteractiveUtil.getProtectedElementsInClass(cdef);
6269 end if;
6270
6271 2 elts := listAppend(InteractiveUtil.getPublicElementsInClass(cdef), elts);
6272 2 result := InteractiveUtil.getElementAnnotationsFromElts(elts, cdef, program, classPath);
6273 end impl;
6274 algorithm
6275 2 result := InteractiveUtil.accessClass(classPath, program, impl, evaluateParams = true);
6276 end getElementAnnotations;
6277
6278 public function getNthComponentAnnotation "
6279 This function takes a `Path\', a `Program\' and an int and
6280 returns a comma separated string of values corresponding to the flat
6281 record for component annotations.
6282 "
6283 input Absyn.Path classPath;
6284 input Integer n;
6285 input Absyn.Program program;
6286 output Values.Value result;
6287 protected
6288 function impl
6289 input Absyn.Path classPath;
6290 input Integer n;
6291 input Absyn.Program program;
6292 input Access accessLevel;
6293 output Values.Value result;
6294 protected
6295 Absyn.Class cdef;
6296 Absyn.Element comp;
6297 algorithm
6298 3 cdef := ProgramUtil.getPathedClassInProgram(classPath, program);
6299 3 comp := InteractiveUtil.getNthComponentInClass(cdef, n);
6300 3 result := InteractiveUtil.getElementAnnotationsFromElts({comp}, cdef, program, classPath);
6301
6302 // Only return an array of arrays if there are multiple components in the same declaration.
6303
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 2 times.
3 if ValuesUtil.isArray(result) and ValuesUtil.arraySize(result) == 1 then
6304 2 result := ValuesUtil.arrayScalar(result);
6305 end if;
6306 end impl;
6307 algorithm
6308 3 result := InteractiveUtil.accessClass(classPath, program, function impl(n = n), evaluateParams = true);
6309 end getNthComponentAnnotation;
6310
6311 public function getNthComponentModification
6312 "Returns the modifier for the n:th component in the given class."
6313 input Absyn.Path classPath;
6314 input Integer n;
6315 input Absyn.Program program;
6316 output Values.Value result;
6317 protected
6318 Absyn.Class cls;
6319 Absyn.Element comp;
6320 algorithm
6321 try
6322 ✗ cls := ProgramUtil.getPathedClassInProgram(classPath, program);
6323 ✗ comp := InteractiveUtil.getNthComponentInClass(cls, n);
6324 ✗ result := getComponentModification(comp);
6325 else
6326 ✗ result := ValuesMake.makeBoolean(false);
6327 end try;
6328 end getNthComponentModification;
6329
6330 public function getNthComponentCondition
6331 "Returns the condition of the n:th component in the given class as a string."
6332 input Absyn.Path classPath;
6333 input Integer n;
6334 input Absyn.Program program;
6335 output Values.Value result;
6336 protected
6337 Absyn.Class cls;
6338 Absyn.Element comp;
6339 String str;
6340 algorithm
6341 try
6342 ✗ cls := ProgramUtil.getPathedClassInProgram(classPath, program);
6343 ✗ comp := InteractiveUtil.getNthComponentInClass(cls, n);
6344 ✗ str := getComponentCondition(comp);
6345 ✗ str := System.trim(str, " ");
6346 ✗ result := ValuesMake.makeString(str);
6347 else
6348 ✗ result := ValuesMake.makeBoolean(false);
6349 end try;
6350 end getNthComponentCondition;
6351
6352 protected function getComponentCondition
6353 " Helper function to getNthComponentCondition."
6354 input Absyn.Element inElement;
6355 output String outString;
6356 algorithm
6357 outString:=
6358 matchcontinue inElement
6359 local
6360 String str;
6361 list<Absyn.ComponentItem> lst;
6362 case Absyn.ELEMENT(specification = Absyn.COMPONENTS(components = lst))
6363 algorithm
6364 ✗ str := getComponentitemsCondition(lst);
6365 then
6366 str;
6367 else "";
6368 end matchcontinue;
6369 end getComponentCondition;
6370
6371 protected function getComponentitemsCondition
6372 "Helper function to getNthComponentCondition."
6373 input list<Absyn.ComponentItem> inAbsynComponentItemLst;
6374 output String outString;
6375 algorithm
6376 outString:=
6377 match inAbsynComponentItemLst
6378 local
6379 String res;
6380 Option<Absyn.ComponentCondition> cond;
6381 case {(Absyn.COMPONENTITEM(condition = cond))}
6382 algorithm
6383 ✗ res := Dump.unparseComponentCondition(cond);
6384 then
6385 res;
6386 end match;
6387 end getComponentitemsCondition;
6388
6389 public function getNthConnection "
6390 This function takes a `ComponentRef\' and a `Program\' and an int and
6391 returns a comma separated string for the nth connection, e.g. \"R1.n,C.p\".
6392 "
6393 input Absyn.ComponentRef inComponentRef;
6394 input Absyn.Program inProgram;
6395 input Integer inInteger;
6396 output list<Values.Value> outValue;
6397 algorithm
6398 outValue:=
6399 matchcontinue (inComponentRef,inProgram,inInteger)
6400 local
6401 Absyn.Path modelpath;
6402 Absyn.Class cdef;
6403 Absyn.Equation eq;
6404 Option<Absyn.Comment> cmt;
6405 list<Values.Value> vals;
6406 String str,s1,s2;
6407 Absyn.ComponentRef model_;
6408 Absyn.Program p;
6409 Integer n;
6410 case (model_,p,n)
6411 algorithm
6412 4 modelpath := AbsynUtil.crefToPath(model_);
6413 4 cdef := ProgramUtil.getPathedClassInProgram(modelpath, p);
6414
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 Absyn.EQUATIONITEM(equation_ = eq, comment = cmt) := listGet(getConnections(cdef), n);
6415 4 str := getStringComment(cmt);
6416 4 (s1, s2) := getConnectionStr(eq);
6417 4 vals := {Values.STRING(s1), Values.STRING(s2), Values.STRING(str)};
6418 then
6419 vals;
6420 else {};
6421 end matchcontinue;
6422 end getNthConnection;
6423
6424 public function getStringComment
6425 input Option<Absyn.Comment> inAbsynCommentOption;
6426 output String outString;
6427 algorithm
6428 outString:=
6429 match inAbsynCommentOption
6430 local String str;
6431 case SOME(Absyn.COMMENT(_,SOME(str))) then str;
6432 else "";
6433 end match;
6434 end getStringComment;
6435
6436 public function addConnection
6437 "Adds a connect equation to the model, i.e. connect(c1,c2)"
6438 input Absyn.Path classPath;
6439 input Absyn.ComponentRef connector1;
6440 input Absyn.ComponentRef connector2;
6441 input Absyn.Exp commentExp;
6442 input Absyn.Exp annotationExp;
6443 input output Absyn.Program program;
6444 output Boolean success;
6445 protected
6446 Absyn.EquationItem eq;
6447 Option<Absyn.Comment> cmt;
6448 algorithm
6449 try
6450 6 cmt := InteractiveUtil.makeCommentFromArgs(commentExp, annotationExp);
6451 6 eq := Absyn.EquationItem.EQUATIONITEM(Absyn.Equation.EQ_CONNECT(connector1, connector2),
6452 cmt, Absyn.dummyInfo);
6453 6 program := transformPathedClassInProgram(classPath, program,
6454 function InteractiveUtil.addToEquation(eq = eq));
6455 success := true;
6456 else
6457 success := false;
6458 end try;
6459 end addConnection;
6460
6461 public function deleteConnection
6462 "Deletes the connection connect(c1,c2) from a model."
6463 input Absyn.Path classPath;
6464 input Absyn.ComponentRef connector1;
6465 input Absyn.ComponentRef connector2;
6466 input output Absyn.Program program;
6467 output Boolean success;
6468 algorithm
6469 try
6470 ✗ program := transformPathedClassInProgram(classPath, program,
6471 function deleteConnectionInClass(connector1 = connector1, connector2 = connector2));
6472 success := true;
6473 else
6474 success := false;
6475 end try;
6476 end deleteConnection;
6477
6478 protected function deleteConnectionInClass
6479 "Helper function to deleteConnection."
6480 input output Absyn.Class cls;
6481 input Absyn.ComponentRef connector1;
6482 input Absyn.ComponentRef connector2;
6483 protected
6484 list<Absyn.EquationItem> eqlst;
6485 Absyn.ClassDef cdef;
6486 algorithm
6487 () := match cls
6488 /* a class with parts */
6489 case Absyn.CLASS(body = cdef as Absyn.PARTS())
6490 algorithm
6491 ✗ eqlst := InteractiveUtil.getEquationList(cdef.classParts);
6492 ✗ eqlst := deleteEquationInEqlist(eqlst, connector1, connector2);
6493 ✗ cdef.classParts := InteractiveUtil.replaceEquationList(cdef.classParts, eqlst);
6494 ✗ cls.body := cdef;
6495 then
6496 ();
6497 /* an extended class with parts: model extends M end M; */
6498 case Absyn.CLASS(body = cdef as Absyn.CLASS_EXTENDS())
6499 algorithm
6500 ✗ eqlst := InteractiveUtil.getEquationList(cdef.parts);
6501 ✗ eqlst := deleteEquationInEqlist(eqlst, connector1, connector2);
6502 ✗ cdef.parts := InteractiveUtil.replaceEquationList(cdef.parts, eqlst);
6503 ✗ cls.body := cdef;
6504 then
6505 ();
6506 end match;
6507 end deleteConnectionInClass;
6508
6509 protected function deleteEquationInEqlist
6510 "Helper function to deleteConnection."
6511 input list<Absyn.EquationItem> inAbsynEquationItemLst1;
6512 input Absyn.ComponentRef inComponentRef2;
6513 input Absyn.ComponentRef inComponentRef3;
6514 output list<Absyn.EquationItem> outAbsynEquationItemLst;
6515 algorithm
6516 outAbsynEquationItemLst := match (inAbsynEquationItemLst1,inComponentRef2,inComponentRef3)
6517 local
6518 list<Absyn.EquationItem> res,xs,loopRes,forEqList;
6519 Absyn.ForIterators forIterator;
6520 Absyn.ComponentRef cn1,cn2,c1,c2;
6521 Absyn.EquationItem x;
6522
6523 case ({},_,_) then {};
6524 case ((Absyn.EQUATIONITEM(equation_ = Absyn.EQ_CONNECT(connector1 = cn1,connector2 = cn2)) :: xs),c1,c2)
6525 guard
6526 AbsynUtil.crefEqual(c1,cn1) and AbsynUtil.crefEqual(c2,cn2)
6527 ✗ then
6528 deleteEquationInEqlist(xs, c1, c2);
6529 case ((Absyn.EQUATIONITEM(equation_ = Absyn.EQ_FOR(forEquations = forEqList, iterators = forIterator)) :: xs),c1,c2)
6530 algorithm
6531 ✗ res := deleteEquationInEqlist(xs, c1, c2);
6532 ✗ loopRes := deleteEquationInEqlist(forEqList, c1, c2);
6533
6534 ✗ if not listEmpty(loopRes) then
6535 ✗ loopRes := { Absyn.EQUATIONITEM(Absyn.EQ_FOR(forIterator, loopRes), NONE(), Absyn.dummyInfo) };
6536 end if;
6537 ✗ then
6538 listAppend(loopRes, res);
6539 case ((x :: xs),c1,c2)
6540 algorithm
6541 ✗ res := deleteEquationInEqlist(xs, c1, c2);
6542 then
6543 (x :: res);
6544 end match;
6545 end deleteEquationInEqlist;
6546
6547 public function addTransition
6548 "Adds a transition to the model, i.e., transition(state1, state2, i > 10)"
6549 input Absyn.ComponentRef inComponentRef;
6550 input String from;
6551 input String to;
6552 input String condition;
6553 input Boolean immediate;
6554 input Boolean reset;
6555 input Boolean synchronize;
6556 input Integer priority;
6557 input list<Absyn.NamedArg> inAbsynNamedArgLst;
6558 input Absyn.Program inProgram;
6559 output Boolean b;
6560 output Absyn.Program outProgram;
6561 algorithm
6562 2 (b,outProgram) := addTransitionWithAnnotation(inComponentRef, from, to, condition, immediate, reset, synchronize, priority, InteractiveUtil.annotationListToAbsyn(inAbsynNamedArgLst), inProgram);
6563 end addTransition;
6564
6565 public function addTransitionWithAnnotation
6566 "Adds a transition to the model, i.e., transition(state1, state2, i > 10)"
6567 input Absyn.ComponentRef inComponentRef;
6568 input String from;
6569 input String to;
6570 input String condition;
6571 input Boolean immediate;
6572 input Boolean reset;
6573 input Boolean synchronize;
6574 input Integer priority;
6575 input Absyn.Annotation inAnnotation;
6576 input Absyn.Program inProgram;
6577 output Boolean b;
6578 output Absyn.Program outProgram;
6579 algorithm
6580 (b,outProgram) := match (inComponentRef, from, to, condition, immediate, reset, synchronize, priority, inAnnotation, inProgram)
6581 local
6582 Absyn.Path modelpath,package_;
6583 Absyn.Class cdef,newcdef;
6584 Absyn.Program newp,p;
6585 Absyn.ComponentRef model_;
6586 String from_, to_, condition_;
6587 Boolean immediate_, reset_, synchronize_;
6588 Integer priority_;
6589 Absyn.Annotation ann;
6590 Option<Absyn.Comment> cmt;
6591 Absyn.Exp conditionExp;
6592
6593 case ((model_ as Absyn.CREF_IDENT()), from_, to_, condition_, immediate_, reset_, synchronize_, priority_, ann,(p as Absyn.PROGRAM()))
6594 algorithm
6595 2 modelpath := AbsynUtil.crefToPath(model_);
6596 2 cdef := ProgramUtil.getPathedClassInProgram(modelpath, p);
6597 2 cmt := SOME(Absyn.COMMENT(SOME(ann), NONE()));
6598
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
2 GlobalScript.ISTMTS({GlobalScript.IEXP(conditionExp, _)}, _) := Parser.parsestringexp(condition_);
6599
6/6
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
✓ Branch 8 taken 1 time.
✓ Branch 9 taken 1 time.
✓ Branch 12 taken 1 time.
✓ Branch 13 taken 1 time.
9 newcdef := InteractiveUtil.addToEquation(cdef, Absyn.EQUATIONITEM(Absyn.EQ_NORETCALL(Absyn.CREF_IDENT("transition", {}),
6600 Absyn.FUNCTIONARGS({Absyn.CREF(Absyn.CREF_IDENT(from_, {})), Absyn.CREF(Absyn.CREF_IDENT(to_, {})),
6601 conditionExp}, {Absyn.NAMEDARG("immediate", Absyn.BOOL(immediate_)),
6602 Absyn.NAMEDARG("reset", Absyn.BOOL(reset_)), Absyn.NAMEDARG("synchronize", Absyn.BOOL(synchronize_)),
6603 Absyn.NAMEDARG("priority", Absyn.INTEGER(priority_))})), cmt, Absyn.dummyInfo));
6604 2 newp := ProgramUtil.updateProgram(Absyn.PROGRAM({newcdef},p.within_), p);
6605 then
6606 (true, newp);
6607
6608 case ((model_ as Absyn.CREF_QUAL()), from_, to_, condition_, immediate_, reset_, synchronize_, priority_, ann,(p as Absyn.PROGRAM()))
6609 algorithm
6610 ✗ modelpath := AbsynUtil.crefToPath(model_);
6611 ✗ cdef := ProgramUtil.getPathedClassInProgram(modelpath, p);
6612 ✗ package_ := AbsynUtil.stripLast(modelpath);
6613 ✗ cmt := SOME(Absyn.COMMENT(SOME(ann), NONE()));
6614 ✗ GlobalScript.ISTMTS({GlobalScript.IEXP(conditionExp, _)}, _) := Parser.parsestringexp(condition_);
6615 ✗ newcdef := InteractiveUtil.addToEquation(cdef, Absyn.EQUATIONITEM(Absyn.EQ_NORETCALL(Absyn.CREF_IDENT("transition", {}),
6616 Absyn.FUNCTIONARGS({Absyn.CREF(Absyn.CREF_IDENT(from_, {})), Absyn.CREF(Absyn.CREF_IDENT(to_, {})),
6617 conditionExp}, {Absyn.NAMEDARG("immediate", Absyn.BOOL(immediate_)),
6618 Absyn.NAMEDARG("reset", Absyn.BOOL(reset_)), Absyn.NAMEDARG("synchronize", Absyn.BOOL(synchronize_)),
6619 Absyn.NAMEDARG("priority", Absyn.INTEGER(priority_))})), cmt, Absyn.dummyInfo));
6620 ✗ newp := ProgramUtil.updateProgram(Absyn.PROGRAM({newcdef},Absyn.WITHIN(package_)), p);
6621 then
6622 (true, newp);
6623 end match;
6624 end addTransitionWithAnnotation;
6625
6626 public function deleteTransition
6627 "Delete the transition transition(c1,c2) from a model."
6628 input Absyn.ComponentRef inComponentRef1;
6629 input String from;
6630 input String to;
6631 input String condition;
6632 input Boolean immediate;
6633 input Boolean reset;
6634 input Boolean synchronize;
6635 input Integer priority;
6636 input Absyn.Program inProgram;
6637 output Boolean b;
6638 output Absyn.Program outProgram;
6639 algorithm
6640 (b,outProgram) := matchcontinue (inComponentRef1, from, to, condition, immediate, reset, synchronize, priority, inProgram)
6641 local
6642 Absyn.Path modelpath,modelwithin;
6643 Absyn.Class cdef,newcdef;
6644 Absyn.Program newp,p;
6645 Absyn.ComponentRef model_;
6646 String from_, to_, condition_;
6647 Boolean immediate_, reset_, synchronize_;
6648 Integer priority_;
6649
6650 case (model_, from_, to_, condition_, immediate_, reset_, synchronize_, priority_ ,(p as Absyn.PROGRAM()))
6651 algorithm
6652 2 modelpath := AbsynUtil.crefToPath(model_);
6653 2 modelwithin := AbsynUtil.stripLast(modelpath);
6654 ✗ cdef := ProgramUtil.getPathedClassInProgram(modelpath, p);
6655 ✗ newcdef := deleteTransitionInClass(cdef, from_, to_, condition_, immediate_, reset_, synchronize_, priority_);
6656 ✗ newp := ProgramUtil.updateProgram(Absyn.PROGRAM({newcdef},Absyn.WITHIN(modelwithin)), p);
6657 then
6658 (true, newp);
6659 case (model_, from_, to_, condition_, immediate_, reset_, synchronize_, priority_ ,(p as Absyn.PROGRAM()))
6660 algorithm
6661 2 modelpath := AbsynUtil.crefToPath(model_);
6662 2 cdef := ProgramUtil.getPathedClassInProgram(modelpath, p);
6663 2 newcdef := deleteTransitionInClass(cdef, from_, to_, condition_, immediate_, reset_, synchronize_, priority_);
6664 2 newp := ProgramUtil.updateProgram(Absyn.PROGRAM({newcdef},Absyn.TOP()), p);
6665 then
6666 (true, newp);
6667 case (_,_,_,_,_,_,_,_,(p as Absyn.PROGRAM())) then (false, p);
6668 end matchcontinue;
6669 end deleteTransition;
6670
6671 protected function deleteTransitionInClass
6672 "Helper function to deleteTransition."
6673 input Absyn.Class inClass;
6674 input String from;
6675 input String to;
6676 input String condition;
6677 input Boolean immediate;
6678 input Boolean reset;
6679 input Boolean synchronize;
6680 input Integer priority;
6681 output Absyn.Class outClass;
6682 algorithm
6683 outClass := match (inClass, from, to, condition, immediate, reset, synchronize, priority)
6684 local
6685 list<Absyn.EquationItem> eqlst,eqlst_1;
6686 list<Absyn.ClassPart> parts2,parts;
6687 String bcname;
6688 Option<String> cmt;
6689 String from_, to_, condition_;
6690 Boolean immediate_, reset_, synchronize_;
6691 Integer priority_;
6692 list<Absyn.ElementArg> modif;
6693 list<String> typeVars;
6694 list<Absyn.NamedArg> classAttrs;
6695 list<Absyn.Annotation> ann;
6696 /* a class with parts */
6697 case (outClass as Absyn.CLASS(
6698 body = Absyn.PARTS(typeVars = typeVars,classAttrs = classAttrs,classParts = parts,ann=ann,comment = cmt),
6699 info = _), from_, to_, condition_, immediate_, reset_, synchronize_, priority_)
6700 algorithm
6701 2 eqlst := InteractiveUtil.getEquationList(parts);
6702 2 eqlst_1 := deleteTransitionInEqlist(eqlst, from_, to_, condition_, immediate_, reset_, synchronize_, priority_);
6703 2 parts2 := InteractiveUtil.replaceEquationList(parts, eqlst_1);
6704 4 outClass.body := Absyn.PARTS(typeVars,classAttrs,parts2,ann,cmt);
6705 then
6706 outClass;
6707 /* an extended class with parts: model extends M end M; */
6708 case (outClass as Absyn.CLASS(
6709 body = Absyn.CLASS_EXTENDS(baseClassName = bcname,modifications=modif,parts = parts,ann = ann,comment = cmt)
6710 ), from_, to_, condition_, immediate_, reset_, synchronize_, priority_)
6711 algorithm
6712 ✗ eqlst := InteractiveUtil.getEquationList(parts);
6713 ✗ eqlst_1 := deleteTransitionInEqlist(eqlst, from_, to_, condition_, immediate_, reset_, synchronize_, priority_);
6714 ✗ parts2 := InteractiveUtil.replaceEquationList(parts, eqlst_1);
6715 ✗ outClass.body := Absyn.CLASS_EXTENDS(bcname,modif,cmt,parts2,ann);
6716 then
6717 outClass;
6718 end match;
6719 end deleteTransitionInClass;
6720
6721 protected function deleteTransitionInEqlist
6722 "Helper function to deleteTransition."
6723 input list<Absyn.EquationItem> inAbsynEquationItemLst;
6724 input String from;
6725 input String to;
6726 input String condition;
6727 input Boolean immediate;
6728 input Boolean reset;
6729 input Boolean synchronize;
6730 input Integer priority;
6731 output list<Absyn.EquationItem> outAbsynEquationItemLst;
6732 algorithm
6733 outAbsynEquationItemLst := matchcontinue (inAbsynEquationItemLst, from, to, condition, immediate, reset, synchronize, priority)
6734 local
6735 list<Absyn.EquationItem> res,xs;
6736 String from_, to_, condition_;
6737 Boolean immediate_, reset_, synchronize_;
6738 Integer priority_;
6739 Absyn.ComponentRef name;
6740 list<Absyn.Exp> expArgs;
6741 list<Absyn.NamedArg> namedArgs;
6742 list<String> args;
6743 Absyn.Exp conditionExp;
6744 Absyn.EquationItem x;
6745
6746 case ({},_,_,_,_,_,_,_) then {};
6747 case ((Absyn.EQUATIONITEM(equation_ = Absyn.EQ_NORETCALL(name, Absyn.FUNCTIONARGS(expArgs, namedArgs))) :: xs), from_, to_, condition_, immediate_, reset_, synchronize_, priority_)
6748 guard AbsynUtil.crefEqual(name, Absyn.CREF_IDENT("transition", {}))
6749 algorithm
6750 8 args := List.map(expArgs, Dump.printExpStr);
6751 8 args := addOrUpdateNamedArg(namedArgs, "immediate", "true", args, 4);
6752 8 args := addOrUpdateNamedArg(namedArgs, "reset", "true", args, 5);
6753 8 args := addOrUpdateNamedArg(namedArgs, "synchronize", "false", args, 6);
6754 8 args := addOrUpdateNamedArg(namedArgs, "priority", "1", args, 7);
6755 // parse the condition string to make it EXP.
6756
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
8 GlobalScript.ISTMTS({GlobalScript.IEXP(conditionExp, _)}, _) := Parser.parsestringexp(condition_);
6757 8 condition_ := Dump.printExpStr(conditionExp);
6758
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
8 true := compareTransitionFuncArgs(args, from_, to_, condition_, immediate_, reset_, synchronize_, priority_);
6759 2 then
6760 deleteTransitionInEqlist(xs, from_, to_, condition_, immediate_, reset_, synchronize_, priority_);
6761 case ((x :: xs), from_, to_, condition_, immediate_, reset_, synchronize_, priority_)
6762 algorithm
6763 10 res := deleteTransitionInEqlist(xs, from_, to_, condition_, immediate_, reset_, synchronize_, priority_);
6764 then
6765 (x :: res);
6766 end matchcontinue;
6767 end deleteTransitionInEqlist;
6768
6769 public function addOrUpdateNamedArg
6770 "Applies the named argument value if it exists.
6771 The named argument override the value of argument if its on same position."
6772 input list<Absyn.NamedArg> inNamedArgLst;
6773 input String namedArg;
6774 input String defaultValue;
6775 input list<String> inTransition;
6776 input Integer position;
6777 output list<String> outTransition;
6778 protected
6779 String namedArgValue;
6780 Boolean isDefault;
6781 algorithm
6782 88 (namedArgValue, isDefault) := namedArgValueAsString(inNamedArgLst, namedArg, defaultValue);
6783
2/2
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 24 times.
88 if listLength(inTransition) < position then
6784 64 outTransition := List.insert(inTransition, position, namedArgValue);
6785 elseif boolAnd((listLength(inTransition) >= position), boolNot(isDefault)) then
6786 6 outTransition := List.replaceAt(namedArgValue, position, inTransition);
6787 else
6788 outTransition := inTransition;
6789 end if;
6790 end addOrUpdateNamedArg;
6791
6792 protected function namedArgValueAsString
6793 "Returns the named argument value as string."
6794 input list<Absyn.NamedArg> inAbsynNamedArgLst;
6795 input String inNamedArg;
6796 input String inDefaultValue;
6797 output String outNamedArg;
6798 output Boolean outDefault;
6799 algorithm
6800 (outNamedArg, outDefault) := match inAbsynNamedArgLst
6801 local
6802 Absyn.NamedArg namedArg;
6803 list<Absyn.NamedArg> al;
6804 Absyn.Ident namedArgName;
6805
6806 case {} then (inDefaultValue,true);
6807
6808 case (namedArg as Absyn.NAMEDARG(argName = namedArgName)) :: _
6809 guard stringEq(namedArgName, inNamedArg)
6810 28 then
6811 (Dump.printNamedArgValueStr(namedArg), false);
6812
6813 case _ :: al
6814 60 then
6815 namedArgValueAsString(al, inNamedArg, inDefaultValue);
6816
6817 end match;
6818 end namedArgValueAsString;
6819
6820 protected function compareTransitionFuncArgs
6821 "Helper function to deleteTransition."
6822 input list<String> args;
6823 input String from;
6824 input String to;
6825 input String condition;
6826 input Boolean immediate;
6827 input Boolean reset;
6828 input Boolean synchronize;
6829 input Integer priority;
6830 output Boolean b;
6831 algorithm
6832 b := matchcontinue (args, from, to, condition, immediate, reset, synchronize, priority)
6833 local
6834 String from1, to1, condition1, immediate1, reset1, synchronize1, priority1, from2, to2, condition2;
6835 Boolean immediate2, reset2, synchronize2;
6836 Integer priority2;
6837
6838 case ({from1, to1, condition1}, from2, to2, condition2, _, _, _, _)
6839 guard
6840 stringEq(from1, from2) and stringEq(to1, to2) and stringEq(condition1, condition2)
6841 then
6842 true;
6843
6844 case ({from1, to1, condition1, immediate1}, from2, to2, condition2, immediate2, _, _, _)
6845 guard
6846 stringEq(from1, from2) and stringEq(to1, to2) and stringEq(condition1, condition2) and stringEq(immediate1, boolString(immediate2))
6847 then
6848 true;
6849
6850 case ({from1, to1, condition1, immediate1, reset1}, from2, to2, condition2, immediate2, reset2, _, _)
6851 guard
6852 stringEq(from1, from2) and stringEq(to1, to2) and stringEq(condition1, condition2) and stringEq(immediate1, boolString(immediate2))
6853 and stringEq(reset1, boolString(reset2))
6854 then
6855 true;
6856
6857 case ({from1, to1, condition1, immediate1, reset1, synchronize1}, from2, to2, condition2, immediate2, reset2, synchronize2, _)
6858 guard
6859 stringEq(from1, from2) and stringEq(to1, to2) and stringEq(condition1, condition2) and stringEq(immediate1, boolString(immediate2))
6860 and stringEq(reset1, boolString(reset2)) and stringEq(synchronize1, boolString(synchronize2))
6861 then
6862 true;
6863
6864 case ({from1, to1, condition1, immediate1, reset1, synchronize1, priority1}, from2, to2, condition2, immediate2, reset2, synchronize2, priority2)
6865 guard
6866 stringEq(from1, from2) and stringEq(to1, to2) and stringEq(condition1, condition2) and stringEq(immediate1, boolString(immediate2))
6867 and stringEq(reset1, boolString(reset2)) and stringEq(synchronize1, boolString(synchronize2)) and stringEq(priority1, intString(priority2))
6868 then
6869 true;
6870
6871 else false;
6872 end matchcontinue;
6873 end compareTransitionFuncArgs;
6874
6875 public function getComponentComment
6876 "Get the component commment."
6877 input Absyn.Path classPath;
6878 input Absyn.Path componentName;
6879 input Absyn.Program program;
6880 output Values.Value comment;
6881 protected
6882 Absyn.Path path;
6883 Absyn.Element elem;
6884 list<Absyn.ComponentItem> comps;
6885 Absyn.ComponentItem comp;
6886 String cmt, comp_name;
6887 algorithm
6888 ✗ path := AbsynUtil.joinPaths(classPath, componentName);
6889 ✗ comp_name := AbsynUtil.pathLastIdent(componentName);
6890 ✗ elem := InteractiveUtil.getPathedElementInProgram(path, program);
6891 ✗ comps := AbsynUtil.getComponentItemsFromElement(elem);
6892 ✗ comp := List.find(comps, function AbsynUtil.isComponentItemNamed(name = comp_name));
6893 ✗ cmt := InteractiveUtil.getClassCommentInCommentOpt(comp.comment);
6894 ✗ comment := ValuesMake.makeString(cmt);
6895 end getComponentComment;
6896
6897 public function setComponentComment
6898 input Absyn.Path classPath;
6899 input Absyn.Path componentName;
6900 input String comment;
6901 input output Absyn.Program program;
6902 output Boolean success;
6903 protected
6904 Absyn.Path path;
6905 String comp_name;
6906 algorithm
6907 try
6908 2 path := AbsynUtil.joinPaths(classPath, componentName);
6909 2 comp_name := AbsynUtil.pathLastIdent(componentName);
6910 2 (program, _, success) := InteractiveUtil.transformPathedElementInProgram(path,
6911 function setComponentCommentInElement(componentName = comp_name, comment = comment), program);
6912 else
6913 ✗ success := false;
6914 end try;
6915 end setComponentComment;
6916
6917 protected function setComponentCommentInElement
6918 input output Absyn.Element element;
6919 input String componentName;
6920 input String comment;
6921 protected
6922 Absyn.ElementSpec spec;
6923 list<Absyn.ComponentItem> comps;
6924
6925 function set_comment
6926 input output Absyn.ComponentItem item;
6927 input String comment;
6928 algorithm
6929
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 item.comment := AbsynUtil.setCommentString(item.comment, if stringEmpty(comment) then NONE() else SOME(comment));
6930 end set_comment;
6931 algorithm
6932 () := match element
6933 case Absyn.Element.ELEMENT(specification = spec as Absyn.ElementSpec.COMPONENTS())
6934 algorithm
6935
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
2 (comps, true) := List.findAndMap(spec.components,
6936 function AbsynUtil.isComponentItemNamed(name = componentName),
6937 function set_comment(comment = comment));
6938 2 spec.components := comps;
6939 2 element.specification := spec;
6940 then
6941 ();
6942 end match;
6943 end setComponentCommentInElement;
6944
6945 public function setConnectionComment
6946 input Absyn.Path classPath;
6947 input Absyn.ComponentRef connector1;
6948 input Absyn.ComponentRef connector2;
6949 input String comment;
6950 input output Absyn.Program program;
6951 output Boolean success;
6952 algorithm
6953 try
6954 2 (program, _, success) := InteractiveUtil.transformPathedElementInProgram(classPath,
6955 function setConnectionCommentInElement(connector1 = connector1, connector2 = connector2, comment = comment),
6956 program);
6957 else
6958 ✗ success := false;
6959 end try;
6960 end setConnectionComment;
6961
6962 protected function setConnectionCommentInElement
6963 input output Absyn.Element element;
6964 input Absyn.ComponentRef connector1;
6965 input Absyn.ComponentRef connector2;
6966 input String comment;
6967 protected
6968 Absyn.ElementSpec spec;
6969 Absyn.Class cls;
6970 algorithm
6971 () := match element
6972 case Absyn.Element.ELEMENT(specification = spec as Absyn.ElementSpec.CLASSDEF())
6973 algorithm
6974 2 cls := setConnectionCommentInClass(spec.class_, connector1, connector2, comment);
6975 2 spec.class_ := cls;
6976 2 element.specification := spec;
6977 then
6978 ();
6979 end match;
6980 end setConnectionCommentInElement;
6981
6982 protected function setConnectionCommentInClass
6983 "Sets the comment on the connection of two connectors in a class."
6984 input output Absyn.Class cls;
6985 input Absyn.ComponentRef connector1;
6986 input Absyn.ComponentRef connector2;
6987 input String comment;
6988 algorithm
6989 () := match cls
6990 local
6991 Absyn.ClassDef cdef;
6992 list<Absyn.ClassPart> parts;
6993
6994 case Absyn.CLASS(body = cdef as Absyn.PARTS())
6995 algorithm
6996 2 parts := setConnectionCommentInParts(cdef.classParts, connector1, connector2, comment);
6997 2 cdef.classParts := parts;
6998 2 cls.body := cdef;
6999 then
7000 ();
7001
7002 case Absyn.CLASS(body = cdef as Absyn.CLASS_EXTENDS())
7003 algorithm
7004 ✗ parts := setConnectionCommentInParts(cdef.parts, connector1, connector2, comment);
7005 ✗ cdef.parts := parts;
7006 ✗ cls.body := cdef;
7007 then
7008 ();
7009 end match;
7010 end setConnectionCommentInClass;
7011
7012 protected function setConnectionCommentInParts
7013 input output list<Absyn.ClassPart> parts;
7014 input Absyn.ComponentRef connector1;
7015 input Absyn.ComponentRef connector2;
7016 input String comment;
7017 algorithm
7018
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 (parts, true) := List.findMap(parts, function setConnectionCommentInEquationsPart(connector1 = connector1,
7019 connector2 = connector2, comment = comment));
7020 end setConnectionCommentInParts;
7021
7022 protected function setConnectionCommentInEquationsPart
7023 input output Absyn.ClassPart part;
7024 input Absyn.ComponentRef connector1;
7025 input Absyn.ComponentRef connector2;
7026 input String comment;
7027 output Boolean found;
7028 protected
7029 list<Absyn.EquationItem> eql;
7030 algorithm
7031 (part, found) := match part
7032 case Absyn.EQUATIONS()
7033 algorithm
7034 2 (eql, found) := List.findMap(part.contents, function setConnectionCommentInEquation(
7035 connector1 = connector1, connector2 = connector2, comment = comment));
7036 2 part.contents := eql;
7037 2 then
7038 (part, found);
7039
7040 else (part, false);
7041 end match;
7042 end setConnectionCommentInEquationsPart;
7043
7044 protected function setConnectionCommentInEquation
7045 input output Absyn.EquationItem eq;
7046 input Absyn.ComponentRef connector1;
7047 input Absyn.ComponentRef connector2;
7048 input String comment;
7049 output Boolean success;
7050 protected
7051 Absyn.ComponentRef c1, c2;
7052 algorithm
7053 success := match eq
7054 case Absyn.EQUATIONITEM(equation_ = Absyn.EQ_CONNECT(connector1 = c1, connector2 = c2))
7055 guard AbsynUtil.crefEqual(connector1, c1) and AbsynUtil.crefEqual(connector2, c2)
7056 algorithm
7057
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 eq.comment := AbsynUtil.setCommentString(eq.comment, if stringEmpty(comment) then NONE() else SOME(comment));
7058 then
7059 true;
7060
7061 else false;
7062 end match;
7063 end setConnectionCommentInEquation;
7064
7065 public function getNthConnectionAnnotation
7066 "This function takes a ComponentRef and a Program and an int and
7067 returns a comma separated string of values for the annotation of
7068 the nth connection."
7069 input Absyn.Path classPath;
7070 input Integer n;
7071 input Absyn.Program program;
7072 output Values.Value result;
7073 protected
7074 function impl
7075 input Absyn.Path classPath;
7076 input Integer n;
7077 input Absyn.Program program;
7078 input Access accessLevel;
7079 output Values.Value result;
7080 protected
7081 Absyn.Class cdef;
7082 Absyn.EquationItem conn;
7083 algorithm
7084 2 cdef := ProgramUtil.getPathedClassInProgram(classPath, program);
7085 2 conn := listGet(getConnections(cdef), n);
7086 2 result := getConnectionAnnotationStr(conn, cdef, program, classPath);
7087 end impl;
7088 algorithm
7089 2 result := InteractiveUtil.accessClass(classPath, program, function impl(n = n),
7090 evaluateParams = true, accessLevel = Access.diagram);
7091 end getNthConnectionAnnotation;
7092
7093 public function getConnectorCount
7094 "This function takes a ComponentRef and a Program and returns the number
7095 of connector components in the class given by the classname in the
7096 ComponentRef. A partial instantiation of the inheritance structure is
7097 performed in order to find all connectors of the class.
7098 inputs: (Absyn.ComponentRef, Absyn.Program)
7099 outputs: string"
7100 input Absyn.Path classPath;
7101 input Absyn.Program program;
7102 output Values.Value result;
7103 protected
7104 Absyn.Class cdef;
7105 algorithm
7106 try
7107 //A complete instantiation is far too expensive. Instead we only
7108 //look through the components of the class for types declared using
7109 //the "connector" restricted class keyword. We also look in
7110 //base classes (recursively).
7111 2 cdef := ProgramUtil.getPathedClassInProgram(classPath, program);
7112 2 result := ValuesMake.makeInteger(countPublicConnectors(classPath, program, cdef));
7113 else
7114 ✗ result := ValuesMake.makeBoolean(false);
7115 end try;
7116 end getConnectorCount;
7117
7118 public function getNthConnector
7119 "Returns the name and type of the n:th connector in the given class."
7120 input Absyn.Path classPath;
7121 input Integer n;
7122 input Absyn.Program program;
7123 output Values.Value result;
7124 protected
7125 Absyn.Class cls;
7126 String name;
7127 Absyn.Path ty;
7128 algorithm
7129 try
7130 ✗ cls := ProgramUtil.getPathedClassInProgram(classPath, program);
7131 ✗ (SOME((name, ty)), _) := getNthPublicConnectorStr(classPath, cls, program, n);
7132 ✗ result := ValuesMake.makeCodeTypeNameArray({Absyn.Path.IDENT(name), ty});
7133 else
7134 ✗ result := ValuesMake.makeBoolean(false);
7135 end try;
7136 end getNthConnector;
7137
7138 public function getNthConnectorIconAnnotation
7139 "Returns the Icon annotation of the type of the n:th public connector in the
7140 given class."
7141 input Absyn.Path classPath;
7142 input Integer n;
7143 input Absyn.Program program;
7144 output Values.Value result;
7145 protected
7146 function impl
7147 input Absyn.Path classPath;
7148 input Integer n;
7149 input Absyn.Program program;
7150 input Access accessLevel;
7151 output Values.Value result;
7152 protected
7153 Absyn.Class cls;
7154 Absyn.Path ty;
7155 algorithm
7156 1 cls := ProgramUtil.getPathedClassInProgram(classPath, program);
7157
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
1 (SOME((_, ty)), _) := getNthPublicConnectorStr(classPath, cls, program, n);
7158 1 result := getIconAnnotation(ty, program);
7159 end impl;
7160 algorithm
7161 1 result := InteractiveUtil.accessClass(classPath, program, function impl(n = n), evaluateParams = true);
7162 end getNthConnectorIconAnnotation;
7163
7164 public function getIconAnnotation
7165 "This function takes a Path and a Program and returns a comma separated
7166 string of values for the icon annotation for the class named by the
7167 first argument."
7168 input Absyn.Path classPath;
7169 input Absyn.Program program;
7170 output Values.Value result;
7171 protected
7172 function impl
7173 input Absyn.Path classPath;
7174 input Absyn.Program program;
7175 input Access accessLevel;
7176 output Values.Value result;
7177 algorithm
7178 17 result := getNamedAnnotationValue(classPath, program, "Icon");
7179 end impl;
7180 algorithm
7181 17 result := InteractiveUtil.accessClass(classPath, program, impl,
7182 evaluateParams = true, graphicsExpMode = true, accessLevel = Access.icon);
7183 end getIconAnnotation;
7184
7185 public function refactorIconAnnotation
7186 input Absyn.Path classPath;
7187 input Absyn.Program program;
7188 output Values.Value result;
7189 protected
7190 function impl
7191 input Absyn.Path classPath;
7192 input Absyn.Program program;
7193 input Access accessLevel;
7194 output Values.Value result;
7195 protected
7196 Absyn.Class cls;
7197 algorithm
7198 ✗ cls := ProgramUtil.getPathedClassInProgram(classPath, program);
7199 ✗ cls := Refactor.refactorGraphicalAnnotation(program, cls);
7200 ✗ result := getNamedAnnotationValue(classPath, program, "Icon");
7201 end impl;
7202 algorithm
7203 ✗ result := InteractiveUtil.accessClass(classPath, program, impl,
7204 evaluateParams = true, graphicsExpMode = true, accessLevel = Access.icon);
7205 end refactorIconAnnotation;
7206
7207 public function getDiagramAnnotation
7208 "This function takes a Path and a Program and returns a comma separated
7209 string of values for the icon annotation for the class named by the
7210 first argument."
7211 input Absyn.Path classPath;
7212 input Absyn.Program program;
7213 output Values.Value result;
7214 protected
7215 function impl
7216 input Absyn.Path classPath;
7217 input Absyn.Program program;
7218 input Access accessLevel;
7219 output Values.Value result;
7220 algorithm
7221 4 result := getNamedAnnotationValue(classPath, program, "Diagram");
7222 end impl;
7223 algorithm
7224 4 result := InteractiveUtil.accessClass(classPath, program, impl,
7225 evaluateParams = true, graphicsExpMode = true, accessLevel = Access.icon);
7226 end getDiagramAnnotation;
7227
7228 public function refactorDiagramAnnotation
7229 input Absyn.Path classPath;
7230 input Absyn.Program program;
7231 output Values.Value result;
7232 protected
7233 function impl
7234 input Absyn.Path classPath;
7235 input Absyn.Program program;
7236 input Access accessLevel;
7237 output Values.Value result;
7238 protected
7239 Absyn.Class cls;
7240 algorithm
7241 ✗ cls := ProgramUtil.getPathedClassInProgram(classPath, program);
7242 ✗ cls := Refactor.refactorGraphicalAnnotation(program, cls);
7243 ✗ result := getNamedAnnotationValue(classPath, program, "Diagram");
7244 end impl;
7245 algorithm
7246 ✗ result := InteractiveUtil.accessClass(classPath, program, impl,
7247 evaluateParams = true, graphicsExpMode = true, accessLevel = Access.icon);
7248 end refactorDiagramAnnotation;
7249
7250 public function getNamedAnnotation
7251 input Absyn.Path classPath;
7252 input Absyn.Path annotationPath;
7253 input Absyn.Program program;
7254 output Values.Value result;
7255 protected
7256 function impl
7257 input Absyn.Path classPath;
7258 input Absyn.Path annotationPath;
7259 input Absyn.Program program;
7260 input Access accessLevel;
7261 output Values.Value result;
7262 protected
7263 String str;
7264 algorithm
7265 ✗ str := ProgramUtil.getNamedAnnotationExp(classPath, program, annotationPath, SOME("{}"), getAnnotationValue);
7266 ✗ result := ValuesMake.makeCodeTypeNameStr(str);
7267 end impl;
7268 algorithm
7269 ✗ result := InteractiveUtil.accessClass(classPath, program,
7270 function impl(annotationPath = annotationPath), evaluateParams = true);
7271 end getNamedAnnotation;
7272
7273
7274
7275 public function getStringNamedAnnotation
7276 "Calls ProgramUtil.getNamedAnnotationExp and makes sure we don't fail if annotation is not String type."
7277 input Absyn.Path inPath;
7278 input Absyn.Program inProgram;
7279 input Absyn.Path id;
7280 output String outString;
7281 algorithm
7282 try
7283
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 Absyn.STRING(outString) := ProgramUtil.getNamedAnnotationExp(inPath, inProgram, id, SOME(Absyn.STRING("")), getAnnotationExp);
7284 else
7285 outString := "";
7286 end try;
7287 end getStringNamedAnnotation;
7288
7289 public function getIntegerNamedAnnotation
7290 "Reads the Integer annotation and converts it to String."
7291 input Absyn.Path inPath;
7292 input Absyn.Program inProgram;
7293 input Absyn.Path id;
7294 output String outString;
7295 protected
7296 Absyn.Class cdef;
7297 Option<Absyn.Exp> exp;
7298 Integer ann;
7299 algorithm
7300 try
7301 6 cdef := ProgramUtil.getPathedClassInProgram(inPath, inProgram);
7302 6 exp := AbsynUtil.getNamedAnnotationInClass(cdef,id,getAnnotationExp);
7303
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if isSome(exp) then
7304 ✗ SOME(Absyn.INTEGER(ann)) := exp;
7305 ✗ outString := intString(ann);
7306 else
7307 outString := "";
7308 end if;
7309 else
7310 outString := "";
7311 end try;
7312 end getIntegerNamedAnnotation;
7313
7314 function getNamedAnnotationValue
7315 input Absyn.Path classPath;
7316 input Absyn.Program program;
7317 input String name;
7318 output Values.Value result;
7319 protected
7320 Absyn.Class cls;
7321 algorithm
7322 21 cls := ProgramUtil.getPathedClassInProgram(classPath, program);
7323 21 result := getNamedAnnotationValueInClass(classPath, cls, program, name);
7324 end getNamedAnnotationValue;
7325
7326 function getNamedAnnotationValueInClass
7327 input Absyn.Path classPath;
7328 input Absyn.Class cls;
7329 input Absyn.Program program;
7330 input String name;
7331 output Values.Value result;
7332 protected
7333 Option<Absyn.Modification> mod;
7334 Absyn.ElementArg arg;
7335 String str;
7336 algorithm
7337 21 mod := AbsynUtil.lookupClassAnnotation(cls, name);
7338
7339 result := match mod
7340 case SOME(Absyn.Modification.CLASSMOD())
7341 algorithm
7342 20 arg := Absyn.ElementArg.MODIFICATION(false, Absyn.Each.NON_EACH(),
7343 Absyn.Path.IDENT(name), mod, NONE(), Absyn.dummyInfo);
7344 20 str := getAnnotationString(Absyn.ANNOTATION({arg}), cls, program, classPath);
7345 20 then
7346 InteractiveUtil.makeAnnotationArrayValue({str});
7347
7348 1 else ValuesMake.makeEmptyArray();
7349 end match;
7350 end getNamedAnnotationValueInClass;
7351
7352 constant Absyn.Path USES_PATH = Absyn.Path.IDENT("uses");
7353
7354 public function getUsesAnnotation
7355 "Returns the uses-annotations of the top-level classes in the given program."
7356 input Absyn.Program program;
7357 output list<Annotation> outUses = {};
7358
7359 type Annotation = tuple<Absyn.Path, String, list<String>, Boolean>;
7360 protected
7361 Option<list<Annotation>> opt_uses;
7362 list<Annotation> uses;
7363 list<Absyn.Class> classes;
7364 algorithm
7365 4986 Absyn.PROGRAM(classes = classes) := program;
7366
7367
2/2
✓ Branch 0 taken 6541 times.
✓ Branch 1 taken 4986 times.
11527 for cls in classes loop
7368 6541 opt_uses := AbsynUtil.getNamedAnnotationInClass(cls, USES_PATH, function getUsesAnnotationString(classOrigin=cls.name));
7369
7370
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6541 times.
✓ Branch 2 taken 600 times.
✓ Branch 3 taken 5941 times.
6541 if isSome(opt_uses) then
7371 600 SOME(uses) := opt_uses;
7372 600 outUses := listAppend(uses, outUses);
7373 end if;
7374 end for;
7375 end getUsesAnnotation;
7376
7377 public function getUsesAnnotationOrDefault
7378 "This function takes a Path and a Program and returns a comma separated
7379 string of values for the Documentation annotation for the class named by the
7380 first argument."
7381 input Absyn.Program p;
7382 input Boolean requireExactVersion;
7383 output list<tuple<Absyn.Path,String,list<String>,Boolean>> usesStr;
7384 protected
7385 list<Absyn.Path> paths;
7386 list<list<String>> strs;
7387 list<String> fromVersions;
7388 algorithm
7389 4986 usesStr := getUsesAnnotation(p);
7390 4986 paths := List.map(usesStr,Util.tuple41);
7391 4986 fromVersions := List.map(usesStr,Util.tuple42);
7392 4986 strs := List.map(usesStr,Util.tuple43);
7393
9/10
✓ Branch 0 taken 1092 times.
✓ Branch 1 taken 4986 times.
✓ Branch 2 taken 1092 times.
✓ Branch 3 taken 4986 times.
✓ Branch 4 taken 1092 times.
✓ Branch 5 taken 4986 times.
✓ Branch 6 taken 1092 times.
✓ Branch 7 taken 4986 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4986 times.
6078 usesStr := list((p,f,s,false) threaded for p in paths, f in fromVersions, s in strs);
7394 end getUsesAnnotationOrDefault;
7395
7396 protected function getUsesAnnotationString
7397 input Option<Absyn.Modification> mod;
7398 input String classOrigin;
7399 output list<tuple<Absyn.Path,String,list<String>,Boolean>> usesStr;
7400 algorithm
7401 usesStr := match mod
7402 local
7403 list<Absyn.ElementArg> arglst;
7404
7405 case SOME(Absyn.CLASSMOD(elementArgLst = arglst))
7406 600 then getUsesAnnotationString2(arglst, classOrigin);
7407
7408 end match;
7409 end getUsesAnnotationString;
7410
7411 protected function getUsesAnnotationString2
7412 input list<Absyn.ElementArg> eltArgs;
7413 input String classOrigin;
7414 output list<tuple<Absyn.Path,String,list<String>,Boolean>> strs;
7415 algorithm
7416 strs := match eltArgs
7417 local
7418 list<Absyn.ElementArg> xs;
7419 String name, version;
7420 list<tuple<Absyn.Path,String,list<String>,Boolean>> ss;
7421 Absyn.Info info;
7422 Option<Absyn.Modification> omod;
7423
7424 case {} then {};
7425
7426 case Absyn.MODIFICATION(path = Absyn.IDENT(name = name),
7427 modification=SOME(Absyn.CLASSMOD(elementArgLst={
7428 Absyn.MODIFICATION(path = Absyn.IDENT(name="version"),modification = omod)
7429 })), info=info)::xs
7430 algorithm
7431 version := match omod
7432 case SOME(Absyn.CLASSMOD(eqMod=Absyn.EQMOD(exp=Absyn.EXPRESSIONCOMMENT(exp=Absyn.STRING(version))))) then version;
7433 case SOME(Absyn.CLASSMOD(eqMod=Absyn.EQMOD(exp=Absyn.STRING(version)))) then version;
7434 else
7435 algorithm
7436 ✗ Error.addSourceMessage(Error.USES_MISSING_VERSION, {name}, info);
7437 then "default";
7438 end match;
7439 1092 ss := getUsesAnnotationString2(xs, classOrigin);
7440 2184 then (Absyn.IDENT(name),classOrigin,{version},false)::ss;
7441
7442 case _::xs
7443 algorithm
7444 ✗ ss := getUsesAnnotationString2(xs, classOrigin);
7445 then ss;
7446
7447 end match;
7448 end getUsesAnnotationString2;
7449
7450 public function getUsedVersion
7451 "Returns the version of a library that the given class uses based on its uses-annotation."
7452 input Absyn.Class cls;
7453 input Absyn.Path library;
7454 output Option<String> version = NONE();
7455 protected
7456 list<tuple<Absyn.Path, String, list<String>, Boolean>> uses;
7457 Absyn.Path lib;
7458 list<String> versions;
7459 algorithm
7460 2 uses := getUsesAnnotationOrDefault(Absyn.Program.PROGRAM({cls}, Absyn.Within.TOP()), true);
7461
7462
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for u in uses loop
7463 1 (lib, _, versions, _) := u;
7464
7465
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 if AbsynUtil.pathEqual(library, lib) then
7466
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if not listEmpty(versions) then
7467 // Assume that a class can only use one version of a specific library.
7468 1 version := SOME(listHead(versions));
7469 1 return;
7470 end if;
7471 end if;
7472 end for;
7473 end getUsedVersion;
7474
7475 public function updateUsedVersion
7476 "Updates the uses annotation for a specific library in a class to a new
7477 version. If the class has no uses annotation for the given library nothing is
7478 done."
7479 input output Absyn.Class cls;
7480 input Absyn.Path library;
7481 input String newVersion;
7482 protected
7483 function make_version_exp
7484 input Absyn.Exp exp;
7485 input String version;
7486 output Absyn.Exp outExp = Absyn.Exp.STRING(version);
7487 end make_version_exp;
7488
7489 Option<Absyn.Annotation> opt_ann;
7490 Absyn.Annotation ann;
7491 Boolean found;
7492 algorithm
7493 1 opt_ann := AbsynUtil.getClassAnnotation(cls);
7494
7495
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 if isNone(opt_ann) then
7496 ✗ return;
7497 end if;
7498
7499 1 SOME(ann) := opt_ann;
7500 1 (ann, found) := AbsynUtil.mapAnnotationBinding(ann,
7501 AbsynUtil.prefixPath("uses", AbsynUtil.joinPaths(library, Absyn.Path.IDENT("version"))),
7502 function make_version_exp(version = newVersion));
7503
7504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if found then
7505 1 cls := AbsynUtil.setClassAnnotation(cls, SOME(ann));
7506 end if;
7507 end updateUsedVersion;
7508
7509 public function getConversionAnnotation
7510 "Returns the conversion-annotations of the top-level classes in the given program."
7511 input Absyn.Class cls;
7512 output list<String> withoutConversion = {}, withConversion = {};
7513 protected
7514 Option<tuple<list<String>,list<String>>> opt_conversion;
7515 algorithm
7516 58 opt_conversion := AbsynUtil.getNamedAnnotationInClass(cls, Absyn.Path.IDENT("conversion"), getConversionAnnotationString);
7517 (withoutConversion,withConversion) := match opt_conversion
7518 case SOME((withoutConversion,withConversion)) then (withoutConversion,withConversion);
7519 else ({},{});
7520 end match;
7521 end getConversionAnnotation;
7522
7523 protected function getConversionAnnotationString
7524 input Option<Absyn.Modification> mod;
7525 output tuple<list<String>,list<String>> result;
7526 protected
7527 list<Absyn.ElementArg> args;
7528 list<String> without = {}, with = {};
7529 list<String> from;
7530 Option<String> script;
7531 algorithm
7532
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 55 times.
55 SOME(Absyn.CLASSMOD(elementArgLst = args)) := mod;
7533
7534
2/2
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 55 times.
226 for arg in args loop
7535 171 (from, _, script) := parseConversionAnnotationElement(arg);
7536
7537
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 171 times.
✓ Branch 2 taken 97 times.
✓ Branch 3 taken 74 times.
171 if isNone(script) then
7538 97 without := List.append_reverse(from, without);
7539 else
7540 74 with := List.append_reverse(from, with);
7541 end if;
7542 end for;
7543
7544 55 result := (listReverse(without), listReverse(with));
7545 end getConversionAnnotationString;
7546
7547 public function getConversionsInClass
7548 input Absyn.Class cls;
7549 output list<tuple<String, Option<String>, Option<String>>> result;
7550 protected
7551 Option<list<tuple<String, Option<String>, Option<String>>>> res;
7552 algorithm
7553 1 res := AbsynUtil.getNamedAnnotationInClass(cls, Absyn.Path.IDENT("conversion"), getConversionsInClassMod);
7554 1 result := Util.getOptionOrDefault(res, {});
7555 end getConversionsInClass;
7556
7557 protected function getConversionsInClassMod
7558 input Option<Absyn.Modification> mod;
7559 output list<tuple<String, Option<String>, Option<String>>> res = {};
7560 protected
7561 list<Absyn.ElementArg> args;
7562 list<String> from;
7563 Option<String> to, script;
7564 algorithm
7565
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 SOME(Absyn.CLASSMOD(elementArgLst = args)) := mod;
7566
7567
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
4 for arg in args loop
7568 3 (from, to, script) := parseConversionAnnotationElement(arg);
7569
7570
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 for v in from loop
7571 3 res := (v, to, script) :: res;
7572 end for;
7573 end for;
7574 end getConversionsInClassMod;
7575
7576 protected function parseConversionAnnotationElement
7577 input Absyn.ElementArg mod;
7578 output list<String> fromVersion = {};
7579 output Option<String> toVersion = NONE();
7580 output Option<String> scriptFilename = NONE();
7581 protected
7582 list<Absyn.ElementArg> args;
7583 Option<Absyn.Modification> arg_mod;
7584 String name;
7585 SourceInfo info;
7586 Absyn.Exp exp;
7587 algorithm
7588 () := match mod
7589 case Absyn.MODIFICATION(path = Absyn.IDENT(name = "noneFromVersion"))
7590 algorithm
7591 97 fromVersion := {AbsynUtil.expString(AbsynUtil.stripCommentExpressions(getAnnotationExp(mod.modification)))};
7592 then
7593 ();
7594
7595 case Absyn.MODIFICATION(path = Absyn.IDENT(name = "from"),
7596 modification = SOME(Absyn.CLASSMOD(elementArgLst = args)))
7597 algorithm
7598
2/2
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 77 times.
233 for arg in args loop
7599
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 156 times.
156 Absyn.MODIFICATION(path = Absyn.IDENT(name = name), modification = arg_mod, info = info) := arg;
7600
7601 () := matchcontinue name
7602 case "version"
7603 algorithm
7604 77 exp := AbsynUtil.stripCommentExpressions(getAnnotationExp(arg_mod));
7605
7606 fromVersion := match exp
7607 37 case Absyn.STRING() then {exp.value};
7608
4/4
✓ Branch 0 taken 280 times.
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 280 times.
✓ Branch 3 taken 40 times.
320 case Absyn.ARRAY() then list(AbsynUtil.expString(e) for e in exp.arrayExp);
7609 end match;
7610 then
7611 ();
7612
7613 case "to"
7614 algorithm
7615 2 toVersion := SOME(AbsynUtil.expString(AbsynUtil.stripCommentExpressions(getAnnotationExp(arg_mod))));
7616 then
7617 ();
7618
7619 case "script"
7620 algorithm
7621 77 scriptFilename := SOME(AbsynUtil.expString(AbsynUtil.stripCommentExpressions(getAnnotationExp(arg_mod))));
7622 then
7623 ();
7624
7625 else
7626 algorithm
7627 ✗ if not StringUtil.startsWith(name, "__") then
7628 ✗ Error.addSourceMessage(Error.CONVERSION_UNKNOWN_ANNOTATION, {name}, info);
7629 end if;
7630 then
7631 ();
7632 end matchcontinue;
7633
7634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 156 times.
156 if listEmpty(fromVersion) then
7635 ✗ Absyn.MODIFICATION(info = info) := mod;
7636 ✗ Error.addSourceMessage(Error.CONVERSION_MISSING_FROM_VERSION,
7637 {Dump.unparseElementArgStr(mod)}, info);
7638 end if;
7639 end for;
7640 then
7641 ();
7642
7643 case Absyn.MODIFICATION(path = Absyn.IDENT(name = name), info = info)
7644 algorithm
7645 ✗ if not StringUtil.startsWith(name, "__") then
7646 ✗ Error.addSourceMessage(Error.CONVERSION_UNKNOWN_ANNOTATION, {name}, info);
7647 end if;
7648 then
7649 ();
7650
7651 else ();
7652 end match;
7653 end parseConversionAnnotationElement;
7654
7655 public function getPackagesInPath
7656 " This function takes a Path and a Program and returns a list of the
7657 names of the packages found in the Path."
7658 input Absyn.Path inPath;
7659 input Absyn.Program inProgram;
7660 output list<Absyn.Path> paths;
7661 algorithm
7662 paths := matchcontinue (inPath,inProgram)
7663 local
7664 Absyn.Class cdef;
7665 Absyn.Path modelpath;
7666 Absyn.Program p;
7667 case (modelpath,p)
7668 algorithm
7669 ✗ cdef := ProgramUtil.getPathedClassInProgram(modelpath, p);
7670 ✗ then getPackagesInClass(modelpath, p, cdef);
7671 else {};
7672 end matchcontinue;
7673 end getPackagesInPath;
7674
7675 public function getTopPackages
7676 " This function takes a Path and a Program and returns a list of the
7677 names of the packages found in the Path."
7678 input Absyn.Program p;
7679 output list<Absyn.Path> paths;
7680 algorithm
7681 ✗ paths := List.map(getTopPackagesInProgram(p),AbsynUtil.makeIdentPathFromString);
7682 end getTopPackages;
7683
7684 protected function getTopPackagesInProgram
7685 "Helper function to getTopPackages."
7686 input Absyn.Program inProgram;
7687 output list<String> outStringLst;
7688 algorithm
7689 outStringLst:=
7690 matchcontinue inProgram
7691 local
7692 list<String> res;
7693 String id;
7694 list<Absyn.Class> rest;
7695 Absyn.Within w;
7696
7697 case Absyn.PROGRAM(classes = {}) then {};
7698 case Absyn.PROGRAM(classes = (Absyn.CLASS(name = id,restriction = Absyn.R_PACKAGE()) :: rest),within_ = w)
7699 algorithm
7700 ✗ res := getTopPackagesInProgram(Absyn.PROGRAM(rest,w));
7701 then
7702 (id :: res);
7703 case Absyn.PROGRAM(classes = (_ :: rest),within_ = w)
7704 algorithm
7705 ✗ res := getTopPackagesInProgram(Absyn.PROGRAM(rest,w));
7706 then
7707 res;
7708 end matchcontinue;
7709 end getTopPackagesInProgram;
7710
7711 protected function getPackagesInClass
7712 " This function takes a Class definition and a Path identifying
7713 the class. It returns a string containing comma separated package
7714 names found in the class definition."
7715 input Absyn.Path inPath;
7716 input Absyn.Program inProgram;
7717 input Absyn.Class inClass;
7718 output list<Absyn.Path> outString;
7719 algorithm
7720 outString:=
7721 match inClass
7722 local
7723 list<String> strlist;
7724 list<Absyn.ClassPart> parts;
7725 /* a class with parts */
7726 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
7727 algorithm
7728 ✗ strlist := getPackagesInParts(parts);
7729 ✗ then List.map(strlist,AbsynUtil.makeIdentPathFromString);
7730 /* an extended class with parts: model extends M end M; */
7731 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
7732 algorithm
7733 ✗ strlist := getPackagesInParts(parts);
7734 ✗ then List.map(strlist,AbsynUtil.makeIdentPathFromString);
7735 /* a derived class */
7736 case Absyn.CLASS(body = Absyn.DERIVED(typeSpec=Absyn.TPATH(_,_)))
7737 algorithm
7738 /* adrpo: 2009-10-27 we shouldn't look into derived!
7739 (cdef,newpath) = lookupClassdef(path, inmodel, p);
7740 res = getPackagesInClass(newpath, p, cdef);
7741 */
7742 then {};
7743 end match;
7744 end getPackagesInClass;
7745
7746 protected function getPackagesInParts
7747 "Helper function to getPackagesInClass."
7748 input list<Absyn.ClassPart> inAbsynClassPartLst;
7749 output list<String> outStringLst;
7750 algorithm
7751 outStringLst:=
7752 match inAbsynClassPartLst
7753 local
7754 list<String> l1,l2,res;
7755 list<Absyn.ElementItem> elts;
7756 list<Absyn.ClassPart> rest;
7757
7758 case {} then {};
7759
7760 case Absyn.PUBLIC(contents = elts) :: rest
7761 algorithm
7762 ✗ l1 := getPackagesInElts(elts);
7763 ✗ l2 := getPackagesInParts(rest);
7764 ✗ res := listAppend(l1, l2);
7765 then
7766 res;
7767
7768 case Absyn.PROTECTED(contents = elts) :: rest
7769 algorithm
7770 ✗ l1 := getPackagesInElts(elts);
7771 ✗ l2 := getPackagesInParts(rest);
7772 ✗ res := listAppend(l1, l2);
7773 then
7774 res;
7775
7776 case _ :: rest
7777 algorithm
7778 ✗ res := getPackagesInParts(rest);
7779 then
7780 res;
7781
7782 end match;
7783 end getPackagesInParts;
7784
7785 protected function getPackagesInElts
7786 "Helper function to getPackagesInParts."
7787 input list<Absyn.ElementItem> inAbsynElementItemLst;
7788 output list<String> outStringLst;
7789 algorithm
7790 outStringLst:=
7791 match inAbsynElementItemLst
7792 local
7793 list<String> res;
7794 String id;
7795 list<Absyn.ElementItem> rest;
7796 case {} then {};
7797 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.CLASSDEF(class_ = Absyn.CLASS(name = id,restriction = Absyn.R_PACKAGE())))) :: rest
7798 algorithm
7799 ✗ res := getPackagesInElts(rest);
7800 then
7801 (id :: res);
7802 case _ :: rest
7803 algorithm
7804 ✗ res := getPackagesInElts(rest);
7805 then
7806 res;
7807 end match;
7808 end getPackagesInElts;
7809
7810 public function getClassnamesInPath
7811 "Return a comma separated list of classes in a given Path."
7812 input Absyn.Path inPath;
7813 input Absyn.Program inProgram;
7814 input Boolean inShowProtected;
7815 input Boolean includeConstants;
7816 output list<Absyn.Path> paths;
7817 algorithm
7818 paths :=
7819 matchcontinue (inPath,inProgram,inShowProtected,includeConstants)
7820 local
7821 Absyn.Class cdef;
7822 Absyn.Path modelpath;
7823 Absyn.Program p;
7824 Boolean b,c;
7825 case (modelpath,p,b,c)
7826 algorithm
7827 9 cdef := ProgramUtil.getPathedClassInProgram(modelpath, p);
7828 9 then ProgramUtil.getClassnamesInClass(modelpath, p, cdef, b, c);
7829 else {};
7830 end matchcontinue;
7831 end getClassnamesInPath;
7832
7833 public function getTopClassnames
7834 " This function takes a Path and a Program and returns a list of
7835 the names of the packages found at the top scope."
7836 input Absyn.Program p;
7837 output list<Absyn.Path> paths;
7838 algorithm
7839 5 paths := List.map(getTopClassnamesInProgram(p),AbsynUtil.makeIdentPathFromString);
7840 end getTopClassnames;
7841
7842 public function getTopClassnamesInProgram
7843 "Helper function to getTopClassnames."
7844 input Absyn.Program inProgram;
7845 output list<String> outStringLst;
7846 algorithm
7847 outStringLst:=
7848 matchcontinue inProgram
7849 local
7850 list<String> res;
7851 String id;
7852 list<Absyn.Class> rest;
7853 Absyn.Within w;
7854
7855 case Absyn.PROGRAM(classes = {}) then {};
7856 case Absyn.PROGRAM(classes = (Absyn.CLASS(name = id) :: rest),within_ = w)
7857 algorithm
7858 7 res := getTopClassnamesInProgram(Absyn.PROGRAM(rest,w));
7859 then
7860 (id :: res);
7861 case Absyn.PROGRAM(classes = (_ :: rest),within_ = w)
7862 algorithm
7863 ✗ res := getTopClassnamesInProgram(Absyn.PROGRAM(rest,w));
7864 then
7865 res;
7866 end matchcontinue;
7867 end getTopClassnamesInProgram;
7868
7869 protected function getTopQualifiedClassnames
7870 "Takes a Program and returns a list of the fully top_qualified
7871 names of the packages found at the top scope.
7872 Example:
7873 within X.Y class Z -> X.Y.Z;"
7874 input Absyn.Program inProgram;
7875 output list<Absyn.Path> outStringLst;
7876 algorithm
7877 outStringLst := matchcontinue inProgram
7878 local
7879 String id;
7880 list<Absyn.Path> res;
7881 list<Absyn.Class> rest;
7882 Absyn.Within w;
7883 Absyn.Path p;
7884
7885 case Absyn.PROGRAM(classes = {}) then {};
7886 case Absyn.PROGRAM(classes = (Absyn.CLASS(name = id) :: rest),within_ = w)
7887 algorithm
7888 6 p := AbsynUtil.joinWithinPath(w, Absyn.IDENT(id));
7889 6 res := getTopQualifiedClassnames(Absyn.PROGRAM(rest,w));
7890 then p::res;
7891 case Absyn.PROGRAM(classes = (_ :: rest),within_ = w)
7892 algorithm
7893 ✗ res := getTopQualifiedClassnames(Absyn.PROGRAM(rest,w));
7894 then
7895 res;
7896 end matchcontinue;
7897 end getTopQualifiedClassnames;
7898
7899 protected function getBaseClasses
7900 " This function gets all base classes of a class, NOT Recursive.
7901 It uses the environment to get the fully qualified names of the classes."
7902 input Absyn.Class cls;
7903 input FCore.Graph env;
7904 output list<Absyn.Path> baseClasses;
7905 protected
7906 String base_class_name;
7907 list<Absyn.ClassPart> parts;
7908 FCore.Graph cenv;
7909 Option<Absyn.Path> env_path_opt;
7910 Absyn.Path env_path, path;
7911 algorithm
7912 baseClasses := matchcontinue cls
7913 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
7914 ✗ then getBaseClassesFromParts(parts, env);
7915
7916 // adrpo: handle the case for model extends baseClassName end baseClassName;
7917 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(baseClassName = base_class_name, parts = parts))
7918 algorithm
7919 ✗ (_, _, cenv) := Lookup.lookupClassIdent(FCore.emptyCache(), env, base_class_name, SOME(cls.info));
7920 ✗ SOME(env_path) := FGraph.getScopePath(cenv);
7921 ✗ path := AbsynUtil.suffixPath(env_path, base_class_name);
7922 ✗ then
7923 path :: getBaseClassesFromParts(parts, env);
7924
7925 case Absyn.CLASS(body = Absyn.DERIVED(typeSpec = Absyn.TPATH(path = path)))
7926 algorithm
7927 ✗ (_, _, cenv) := Lookup.lookupClass(FCore.emptyCache(), env, path, SOME(cls.info));
7928 ✗ env_path_opt := FGraph.getScopePath(cenv);
7929
7930 ✗ if isSome(env_path_opt) then
7931 ✗ path := AbsynUtil.suffixPath(Util.getOption(env_path_opt), AbsynUtil.pathLastIdent(path));
7932 end if;
7933 then
7934 {path};
7935
7936 else {};
7937 end matchcontinue;
7938 end getBaseClasses;
7939
7940 protected function getBaseClassesFromParts
7941 "Helper function to getBaseClasses."
7942 input list<Absyn.ClassPart> parts;
7943 input FCore.Graph env;
7944 output list<Absyn.Path> baseClasses = {};
7945 algorithm
7946 ✗ for part in parts loop
7947 ✗ for el in AbsynUtil.getElementItemsInClassPart(part) loop
7948 ✗ baseClasses := getBaseClassesFromElt(el, env, baseClasses);
7949 end for;
7950 end for;
7951
7952 ✗ baseClasses := Dangerous.listReverseInPlace(baseClasses);
7953 end getBaseClassesFromParts;
7954
7955 protected function getBaseClassesFromElt
7956 "Helper function to getBaseClassesFromParts."
7957 input Absyn.ElementItem element;
7958 input FCore.Graph env;
7959 input output list<Absyn.Path> baseClasses;
7960 protected
7961 Absyn.Path path;
7962 SourceInfo info;
7963 FCore.Graph cenv;
7964 Option<Absyn.Path> env_path_opt;
7965 algorithm
7966 baseClasses := matchcontinue element
7967 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.EXTENDS(path = path), info = info))
7968 algorithm
7969 ✗ (_, _, cenv) := Lookup.lookupClass(FCore.emptyCache(), env, path, SOME(info));
7970 ✗ env_path_opt := FGraph.getScopePath(cenv);
7971
7972 ✗ if isSome(env_path_opt) then
7973 ✗ path := AbsynUtil.suffixPath(Util.getOption(env_path_opt), AbsynUtil.pathLastIdent(path));
7974 end if;
7975 then
7976 path :: baseClasses;
7977
7978 ✗ else baseClasses;
7979 end matchcontinue;
7980 end getBaseClassesFromElt;
7981
7982 protected function countBaseClasses
7983 " This function counts the number of base classes of a class"
7984 input Absyn.Class inClass;
7985 output Integer count;
7986 protected
7987 list<Absyn.ClassPart> parts;
7988 algorithm
7989 count := match inClass
7990 ✗ case Absyn.CLASS(body = Absyn.PARTS(classParts = parts)) then countBaseClassesFromParts(parts);
7991 // adrpo: add the case for model extends baseClassName extends SomeElseClass; end baseClassName;
7992 ✗ case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)) then countBaseClassesFromParts(parts);
7993 case Absyn.CLASS(body = Absyn.DERIVED()) then 1;
7994 else 0;
7995 end match;
7996 end countBaseClasses;
7997
7998 protected function countBaseClassesFromParts
7999 "Helper function to countBaseClasses."
8000 input list<Absyn.ClassPart> parts;
8001 output Integer count = 0;
8002 algorithm
8003 ✗ for part in parts loop
8004 ✗ for el in AbsynUtil.getElementItemsInClassPart(part) loop
8005 ✗ if AbsynUtil.isElementItemExtends(el) then
8006 ✗ count := count + 1;
8007 end if;
8008 end for;
8009 end for;
8010 end countBaseClassesFromParts;
8011
8012 public function getDocumentationClassAnnotation
8013 "Returns the documentation class annotation of a class.
8014 This is annotated with the annotation:
8015 annotation (DocumentationClass=true); in the class definition"
8016 input Absyn.Path className;
8017 input Absyn.Program p;
8018 output Boolean isDocClass;
8019 algorithm
8020 isDocClass := match p
8021 local
8022 String docStr;
8023 case _
8024 algorithm
8025 6 docStr := ProgramUtil.getNamedAnnotationExp(className,p,Absyn.IDENT("DocumentationClass"),SOME("false"),getDocumentationClassAnnotationModStr);
8026
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 then
8027 stringEq(docStr, "true");
8028 end match;
8029 end getDocumentationClassAnnotation;
8030
8031 protected function getDocumentationClassAnnotationModStr
8032 "Extractor function for DocumentationClass"
8033 input Option<Absyn.Modification> mod;
8034 output String docStr;
8035 algorithm
8036 docStr := matchcontinue mod
8037 local Absyn.Exp e;
8038
8039 case SOME(Absyn.CLASSMOD(eqMod = Absyn.EQMOD(exp=e)))
8040 algorithm
8041 ✗ docStr := Dump.printExpStr(e);
8042 then
8043 docStr;
8044
8045 else "false";
8046
8047 end matchcontinue;
8048 end getDocumentationClassAnnotationModStr;
8049
8050 public function getDefaultComponentName
8051 input Absyn.Path classPath;
8052 input Absyn.Program program;
8053 output Values.Value result;
8054 protected
8055 String str;
8056 algorithm
8057 2 str := getStringNamedAnnotation(classPath, program, Absyn.IDENT("defaultComponentName"));
8058 2 result := ValuesMake.makeString(str);
8059 end getDefaultComponentName;
8060
8061 public function getDefaultComponentPrefixes
8062 input Absyn.Path classPath;
8063 input Absyn.Program program;
8064 output Values.Value result;
8065 protected
8066 String str;
8067 algorithm
8068 4 str := getStringNamedAnnotation(classPath, program, Absyn.IDENT("defaultComponentPrefixes"));
8069 4 result := ValuesMake.makeString(str);
8070 end getDefaultComponentPrefixes;
8071
8072 protected function getAnnotationValue
8073 input Option<Absyn.Modification> mod;
8074 output String str;
8075 protected
8076 Absyn.Exp exp;
8077 algorithm
8078 str := matchcontinue mod
8079 case SOME(Absyn.CLASSMOD(elementArgLst = {}, eqMod=Absyn.EQMOD(exp=exp)))
8080 ✗ then "{" + Dump.printExpStr(exp) + "}";
8081
8082 // adrpo: empty if no value
8083 else "{}";
8084 end matchcontinue;
8085 end getAnnotationValue;
8086
8087 public function getAnnotationExp
8088 input Option<Absyn.Modification> mod;
8089 output Absyn.Exp exp;
8090 algorithm
8091
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1080 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1080 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1080 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1080 times.
1080 SOME(Absyn.CLASSMOD(elementArgLst = {}, eqMod=Absyn.EQMOD(exp=exp))) := mod;
8092 end getAnnotationExp;
8093
8094 public function getAnnotationStringValueOrFail
8095 input Option<Absyn.Modification> mod;
8096 output String str;
8097 algorithm
8098 str := match mod
8099 local
8100 Absyn.Exp exp;
8101 58 case SOME(Absyn.CLASSMOD(elementArgLst = {}, eqMod=Absyn.EQMOD(exp=exp))) then AbsynUtil.getString(exp);
8102 end match;
8103 end getAnnotationStringValueOrFail;
8104
8105 public function getExperimentAnnotationString
8106 "@author: adrpo
8107 gets the experiment annotation values"
8108 input Option<Absyn.Modification> mod;
8109 output String experimentStr;
8110 algorithm
8111 experimentStr := match mod
8112 local
8113 list<Absyn.ElementArg> arglst;
8114 list<String> strs;
8115 String s;
8116
8117 case SOME(Absyn.CLASSMOD(elementArgLst = arglst))
8118 algorithm
8119 449 strs := getExperimentAnnotationString2(arglst);
8120 449 s := stringDelimitList(strs,",");
8121 449 s := stringAppendList({"{", s, "}"});
8122 then
8123 s;
8124
8125 end match;
8126 end getExperimentAnnotationString;
8127
8128 protected function getExperimentAnnotationString2
8129 "Helper function to getExperimentAnnotationString"
8130 input list<Absyn.ElementArg> eltArgs;
8131 output list<String> strs;
8132 algorithm
8133 strs := matchcontinue eltArgs
8134 local
8135 Absyn.Exp exp;
8136 list<Absyn.ElementArg> xs;
8137 String name, s;
8138 list<String> ss;
8139
8140 case {} then {};
8141
8142 case Absyn.MODIFICATION(path = Absyn.IDENT(name = name),
8143 modification=SOME(Absyn.CLASSMOD(eqMod=Absyn.EQMOD(exp=exp))))::xs
8144 algorithm
8145 781 s := name + "=" + Dump.printExpStr(exp);
8146 781 ss := getExperimentAnnotationString2(xs);
8147 then s::ss;
8148
8149 case _::xs
8150 algorithm
8151 ✗ ss := getExperimentAnnotationString2(xs);
8152 then ss;
8153
8154 end matchcontinue;
8155 end getExperimentAnnotationString2;
8156
8157 public function getDocumentationAnnotationString
8158 input Option<Absyn.Modification> mod;
8159 output tuple<String,String,String> docStr;
8160 algorithm
8161 docStr := match mod
8162 local
8163 list<Absyn.ElementArg> arglst;
8164 String info, revisions, infoHeader;
8165 Boolean partialInst;
8166 case SOME(Absyn.CLASSMOD(elementArgLst = arglst))
8167 algorithm
8168 11 partialInst := System.getPartialInstantiation();
8169 11 System.setPartialInstantiation(true);
8170 11 info := getDocumentationAnnotationInfo(arglst);
8171 11 revisions := getDocumentationAnnotationRevision(arglst);
8172 11 infoHeader := getDocumentationAnnotationInfoHeader(arglst);
8173 11 System.setPartialInstantiation(partialInst);
8174 11 then ((info,revisions,infoHeader));
8175 end match;
8176 end getDocumentationAnnotationString;
8177
8178 protected function getDocumentationAnnotationInfo
8179 "Helper function to getDocumentationAnnotationString"
8180 input list<Absyn.ElementArg> eltArgs;
8181 output String str;
8182 algorithm
8183 str := matchcontinue eltArgs
8184 local
8185 Absyn.Exp exp;
8186 DAE.Exp dexp;
8187 list<Absyn.ElementArg> xs;
8188 String s;
8189 String ss;
8190 case {} then "";
8191 case Absyn.MODIFICATION(path = Absyn.IDENT(name = "info"),
8192 modification=SOME(Absyn.CLASSMOD(eqMod=Absyn.EQMOD(exp=exp))))::_
8193 algorithm
8194 11 (_,dexp,_) := StaticScript.elabGraphicsExp(FCore.emptyCache(), FGraph.empty(), exp, true, DAE.NOPRE(), Absyn.dummyInfo);
8195
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 (DAE.SCONST(s),_) := ExpressionSimplify.simplify(dexp);
8196 // ss = getDocumentationAnnotationInfo(xs);
8197 then s;
8198 case _::xs
8199 algorithm
8200 2 ss := getDocumentationAnnotationInfo(xs);
8201 then ss;
8202 end matchcontinue;
8203 end getDocumentationAnnotationInfo;
8204
8205 protected function getDocumentationAnnotationRevision
8206 "Helper function to getDocumentationAnnotationString"
8207 input list<Absyn.ElementArg> eltArgs;
8208 output String str;
8209 algorithm
8210 str := matchcontinue eltArgs
8211 local
8212 Absyn.Exp exp;
8213 list<Absyn.ElementArg> xs;
8214 String s;
8215 String ss;
8216 DAE.Exp dexp;
8217 case {} then "";
8218 case Absyn.MODIFICATION(path = Absyn.IDENT(name = "revisions"),
8219 modification=SOME(Absyn.CLASSMOD(eqMod=Absyn.EQMOD(exp=exp))))::_
8220 algorithm
8221 5 (_,dexp,_) := StaticScript.elabGraphicsExp(FCore.emptyCache(), FGraph.empty(), exp, true, DAE.NOPRE(), Absyn.dummyInfo);
8222
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 (DAE.SCONST(s),_) := ExpressionSimplify.simplify(dexp);
8223 then s;
8224 case _::xs
8225 algorithm
8226 10 ss := getDocumentationAnnotationRevision(xs);
8227 then ss;
8228 end matchcontinue;
8229 end getDocumentationAnnotationRevision;
8230
8231 protected function getDocumentationAnnotationInfoHeader
8232 "Helper function to getDocumentationAnnotationString"
8233 input list<Absyn.ElementArg> eltArgs;
8234 output String str;
8235 algorithm
8236 str := matchcontinue eltArgs
8237 local
8238 Absyn.Exp exp;
8239 list<Absyn.ElementArg> xs;
8240 String s;
8241 String ss;
8242 DAE.Exp dexp;
8243 case {} then "";
8244 case Absyn.MODIFICATION(path = Absyn.IDENT(name = "__OpenModelica_infoHeader"),
8245 modification=SOME(Absyn.CLASSMOD(eqMod=Absyn.EQMOD(exp=exp))))::_
8246 algorithm
8247 1 (_,dexp,_) := StaticScript.elabGraphicsExp(FCore.emptyCache(), FGraph.empty(), exp, true, DAE.NOPRE(), Absyn.dummyInfo);
8248
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 (DAE.SCONST(s),_) := ExpressionSimplify.simplify(dexp);
8249 then s;
8250 case _::xs
8251 algorithm
8252 16 ss := getDocumentationAnnotationInfoHeader(xs);
8253 then ss;
8254 end matchcontinue;
8255 end getDocumentationAnnotationInfoHeader;
8256
8257 protected function getNthPublicConnectorStr
8258 "Returns the n:th connector's name and type in the given class, or n minus
8259 the number of connectors found if n is too large."
8260 input Absyn.Path classPath;
8261 input Absyn.Class cls;
8262 input Absyn.Program program;
8263 output Option<tuple<String, Absyn.Path>> conn = NONE();
8264 input output Integer n;
8265 protected
8266 list<Absyn.ClassPart> parts;
8267 algorithm
8268 1 parts := AbsynUtil.getClassPartsInClass(cls);
8269
8270
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 for part in parts loop
8271 (conn, n) := match part
8272 1 case Absyn.PUBLIC() then getNthConnectorInfo(program, classPath, part.contents, n);
8273 ✗ else (conn, n);
8274 end match;
8275
8276
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if n <= 0 then
8277 break;
8278 end if;
8279 end for;
8280 end getNthPublicConnectorStr;
8281
8282 protected function getNthConnectorInfo
8283 "Returns the n:th connector's name and type in the given list of element
8284 items, or n minus the number of connectors found if n is too large."
8285 input Absyn.Program program;
8286 input Absyn.Path classPath;
8287 input list<Absyn.ElementItem> items;
8288 output Option<tuple<String, Absyn.Path>> conn = NONE();
8289 input output Integer n;
8290 protected
8291 Absyn.Path tp, cls_path;
8292 Absyn.Class cls;
8293 list<Absyn.ComponentItem> comps;
8294 Integer comp_count;
8295 String name;
8296 algorithm
8297
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 for item in items loop
8298 (conn, n) := match item
8299 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.EXTENDS(path = tp)))
8300 algorithm
8301 ✗ (cls, cls_path) := lookupClassdef(tp, classPath, program);
8302 ✗ then
8303 getNthPublicConnectorStr(cls_path, cls, program, n);
8304
8305 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.COMPONENTS(
8306 typeSpec = Absyn.TPATH(path = tp), components = comps)))
8307 algorithm
8308 1 (cls, _) := lookupClassdef(tp, classPath, program);
8309
8310
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if AbsynUtil.isConnector(cls) or AbsynUtil.isExpandableConnector(cls) then
8311 1 comp_count := listLength(comps);
8312
8313
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if n <= comp_count then
8314 1 name := AbsynUtil.componentName(listGet(comps, n));
8315 1 conn := SOME((name, tp));
8316 end if;
8317
8318 1 n := n - comp_count;
8319 end if;
8320 1 then
8321 (conn, n);
8322
8323 ✗ else (conn, n);
8324 end match;
8325
8326
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if n <= 0 then
8327 break;
8328 end if;
8329 end for;
8330 end getNthConnectorInfo;
8331
8332 protected function countPublicConnectors
8333 "This function takes a Class and counts the number of connector
8334 components in the class. This also includes counting in inherited classes."
8335 input Absyn.Path classPath;
8336 input Absyn.Program program;
8337 input Absyn.Class cls;
8338 output Integer count;
8339 protected
8340 list<Absyn.ClassPart> parts;
8341 Absyn.Class cdef;
8342 Absyn.Path cls_name;
8343 algorithm
8344 count := match cls
8345 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
8346 3 then countPublicConnectorsInParts(parts, classPath, program);
8347
8348 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
8349 ✗ then countPublicConnectorsInParts(parts, classPath, program);
8350
8351 case Absyn.CLASS(body = Absyn.DERIVED(typeSpec = Absyn.TPATH(path = cls_name)))
8352 algorithm
8353 ✗ (cdef, _) := lookupClassdef(cls_name, classPath, program);
8354 ✗ then
8355 countPublicConnectors(classPath, program, cdef);
8356
8357 else 0;
8358 end match;
8359 end countPublicConnectors;
8360
8361 protected function countPublicConnectorsInParts
8362 input list<Absyn.ClassPart> parts;
8363 input Absyn.Path classPath;
8364 input Absyn.Program program;
8365 output Integer count = 0;
8366 algorithm
8367
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 for part in parts loop
8368 count := match part
8369 3 case Absyn.ClassPart.PUBLIC() then count + countConnectors(classPath, program, part.contents);
8370 else count;
8371 end match;
8372 end for;
8373 end countPublicConnectorsInParts;
8374
8375 protected function countConnectors
8376 "This function takes a Path to the current model and a ElementItem
8377 list and returns the number of connector components in that list."
8378 input Absyn.Path classPath;
8379 input Absyn.Program program;
8380 input list<Absyn.ElementItem> items;
8381 output Integer count = 0;
8382 protected
8383 Absyn.Class cls;
8384 Absyn.Path tp, cls_path;
8385 list<Absyn.ComponentItem> comps;
8386 Integer c;
8387 algorithm
8388
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 for item in items loop
8389 c := matchcontinue item
8390 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.EXTENDS(path = tp)))
8391 algorithm
8392 1 (cls, cls_path) := lookupClassdef(tp, classPath, program);
8393 1 then
8394 countPublicConnectors(cls_path, program, cls);
8395
8396 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification =
8397 Absyn.COMPONENTS(typeSpec = Absyn.TPATH(tp), components = comps)))
8398 algorithm
8399 5 (cls, _) := lookupClassdef(tp, classPath, program);
8400
3/4
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
5 then
8401 if AbsynUtil.isConnector(cls) or AbsynUtil.isExpandableConnector(cls) then listLength(comps) else 0;
8402
8403 else 0;
8404 end matchcontinue;
8405
8406 6 count := count + c;
8407 end for;
8408 end countConnectors;
8409
8410 protected function getConnectionAnnotationStrElArgs
8411 input list<Absyn.ElementArg> inElArgLst;
8412 input SourceInfo info;
8413 input Absyn.Class inClass;
8414 input Absyn.Program inFullProgram;
8415 input Absyn.Path inModelPath;
8416 output list<String> outStringLst;
8417 algorithm
8418 outStringLst := matchcontinue inElArgLst
8419 local
8420 Absyn.FunctionArgs fargs;
8421 list<SCode.Element> p_1;
8422 FCore.Graph env;
8423 DAE.Exp newexp;
8424 String gexpstr, gexpstr_1, annName;
8425 list<String> res;
8426 list<Absyn.ElementArg> mod, rest;
8427 FCore.Cache cache;
8428 DAE.Properties prop;
8429 Absyn.Program lineProgram;
8430
8431 // handle empty
8432 case {} then {};
8433
8434 case Absyn.MODIFICATION(path = Absyn.IDENT(annName), modification = SOME(Absyn.CLASSMOD(mod,_))) :: rest
8435 algorithm
8436 2 lineProgram := InteractiveUtil.modelicaAnnotationProgram(Config.getAnnotationVersion());
8437 2 fargs := createFuncargsFromElementargs(mod);
8438 2 p_1 := AbsynToSCode.translateAbsyn2SCode(lineProgram);
8439 2 (cache,env) := Inst.makeEnvFromProgram(p_1);
8440 2 (_,newexp,prop) := StaticScript.elabGraphicsExp(cache,env, Absyn.CALL(Absyn.CREF_IDENT(annName,{}),fargs,{}), false,DAE.NOPRE(), info) "impl" ;
8441 2 (cache, newexp, prop) := Ceval.cevalIfConstant(cache, env, newexp, prop, false, info);
8442 2 Print.clearErrorBuf() "this is to clear the error-msg generated by the annotations." ;
8443 2 gexpstr := ExpressionBasics.printExpStr(newexp);
8444 2 res := getConnectionAnnotationStrElArgs(rest, info, inClass, inFullProgram, inModelPath);
8445 then
8446 (gexpstr :: res);
8447 case Absyn.MODIFICATION(path = Absyn.IDENT(annName), modification = SOME(Absyn.CLASSMOD(_,Absyn.NOMOD()))) :: rest
8448 algorithm
8449 ✗ gexpstr_1 := stringAppendList({annName,"(error)"});
8450 ✗ res := getConnectionAnnotationStrElArgs(rest, info, inClass, inFullProgram, inModelPath);
8451 then
8452 (gexpstr_1 :: res);
8453 end matchcontinue;
8454 end getConnectionAnnotationStrElArgs;
8455
8456 protected function getConnectionAnnotationStr
8457 " This function takes an `EquationItem\' and returns a comma separated
8458 string of values from the flat record of a connection annotation that
8459 is found in the `EquationItem\'."
8460 input Absyn.EquationItem inEquationItem;
8461 input Absyn.Class inClass;
8462 input Absyn.Program inFullProgram;
8463 input Absyn.Path inModelPath;
8464 output Values.Value result;
8465 protected
8466 list<String> res;
8467 list<Absyn.ElementArg> annotations;
8468 SourceInfo info;
8469 algorithm
8470 result := match inEquationItem
8471 case Absyn.EQUATIONITEM(info=info, equation_ = Absyn.EQ_CONNECT(),
8472 comment = SOME(Absyn.COMMENT(annotation_ = SOME(Absyn.ANNOTATION(annotations)))))
8473 algorithm
8474 2 res := getConnectionAnnotationStrElArgs(annotations, info, inClass, inFullProgram, inModelPath);
8475 2 then
8476 InteractiveUtil.makeAnnotationArrayValue(res);
8477 end match;
8478 end getConnectionAnnotationStr;
8479
8480 public function createFuncargsFromElementargs
8481 "Trasform an ElementArg list to function argments. This is used when
8482 translating a graphical annotation to a record constructor."
8483 input list<Absyn.ElementArg> inAbsynElementArgLst;
8484 output Absyn.FunctionArgs outFunctionArgs;
8485 algorithm
8486 outFunctionArgs := matchcontinue inAbsynElementArgLst
8487 local
8488 list<Absyn.Exp> expl;
8489 list<Absyn.NamedArg> narg;
8490 String id;
8491 Absyn.Exp exp;
8492 list<Absyn.ElementArg> xs;
8493
8494 case {} then Absyn.FUNCTIONARGS({},{});
8495
8496 case Absyn.MODIFICATION(path = Absyn.IDENT(name = id),modification = SOME(Absyn.CLASSMOD(eqMod=Absyn.EQMOD(exp=exp)))) :: xs
8497 algorithm
8498
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 Absyn.FUNCTIONARGS(expl,narg) := createFuncargsFromElementargs(xs);
8499 92 then
8500 Absyn.FUNCTIONARGS(expl,(Absyn.NAMEDARG(id,exp) :: narg));
8501
8502 case _ :: xs
8503 algorithm
8504 ✗ Absyn.FUNCTIONARGS(expl,narg) := createFuncargsFromElementargs(xs);
8505 ✗ then
8506 Absyn.FUNCTIONARGS(expl,narg);
8507 end matchcontinue;
8508 end createFuncargsFromElementargs;
8509
8510 protected function getConnectionStr
8511 " This function takes an Equation assumed to contain a connection and
8512 returns a comma separated string of componentreferences, e.g \"R1.n,C.p\"
8513 for connect(R1.n,C.p)."
8514 input Absyn.Equation inEquation;
8515 output String outFromString;
8516 output String outToString;
8517 algorithm
8518 (outFromString, outToString) := match inEquation
8519 local
8520 String s1,s2;
8521 Absyn.ComponentRef cr1,cr2;
8522
8523 case Absyn.EQ_CONNECT(connector1 = cr1,connector2 = cr2)
8524 algorithm
8525 4 s1 := Dump.printComponentRefStr(cr1);
8526 4 s2 := Dump.printComponentRefStr(cr2);
8527 then
8528 (s1, s2);
8529 end match;
8530 end getConnectionStr;
8531
8532 public function getConnections
8533 "This function takes a Class and returns a list of connections in the Class."
8534 input Absyn.Class inClass;
8535 output list<Absyn.EquationItem> connections;
8536 algorithm
8537 8 connections := getConnectionsInClassparts(AbsynUtil.getClassPartsInClass(inClass));
8538 end getConnections;
8539
8540 protected function getConnectionsInClassparts
8541 " This function takes a ClassPart list and returns
8542 a list of connections in that list."
8543 input list<Absyn.ClassPart> inAbsynClassPartLst;
8544 output list<Absyn.EquationItem> outList;
8545 algorithm
8546 outList := match inAbsynClassPartLst
8547 local
8548 list<Absyn.EquationItem> eqlist1, eqlist2;
8549 list<Absyn.ClassPart> xs;
8550
8551 case Absyn.EQUATIONS(contents = eqlist1) :: xs
8552 algorithm
8553 8 eqlist1 := getConnectionsInEquations(eqlist1);
8554 8 eqlist2 := getConnectionsInClassparts(xs);
8555 8 then
8556 listAppend(eqlist1, eqlist2);
8557
8558 case _ :: xs
8559 algorithm
8560 14 eqlist1 := getConnectionsInClassparts(xs);
8561 then
8562 eqlist1;
8563
8564 case {} then {};
8565
8566 end match;
8567 end getConnectionsInClassparts;
8568
8569 protected function getConnectionsInEquations
8570 " This function takes an Equation list and returns a list
8571 of connect statements in that list."
8572 input list<Absyn.EquationItem> inAbsynEquationItemLst;
8573 output list<Absyn.EquationItem> outList;
8574 algorithm
8575 outList := match inAbsynEquationItemLst
8576 local
8577 Absyn.EquationItem eq;
8578 list<Absyn.EquationItem> eqlist1, eqlist2;
8579 list<Absyn.EquationItem> xs;
8580 list<Absyn.EquationItem> forEqList;
8581
8582 case (eq as Absyn.EQUATIONITEM(equation_ = Absyn.EQ_CONNECT())) :: xs
8583 algorithm
8584 10 eqlist1 := getConnectionsInEquations(xs);
8585 then
8586 eq::eqlist1;
8587
8588
8589 case Absyn.EQUATIONITEM(equation_ = Absyn.EQ_FOR(forEquations = forEqList)) :: xs
8590 algorithm
8591 ✗ eqlist1 := getConnectionsInEquations(forEqList);
8592 ✗ eqlist2 := getConnectionsInEquations(xs);
8593 ✗ then
8594 listAppend(eqlist1, eqlist2);
8595
8596 case _ :: xs
8597 algorithm
8598 ✗ eqlist1 := getConnectionsInEquations(xs);
8599 then
8600 eqlist1;
8601
8602 case {} then {};
8603
8604 end match;
8605 end getConnectionsInEquations;
8606
8607 public function getComponentModification
8608 " This function takes an Element and returns a comma separated
8609 list of Code expression for the modification of the component."
8610 input Absyn.Element element;
8611 output Values.Value result;
8612 protected
8613 list<Absyn.ComponentItem> comps;
8614 Option<Absyn.Modification> opt_mod;
8615 Absyn.Modification mod;
8616 list<Values.Value> vals = {};
8617 algorithm
8618 result := match element
8619 case Absyn.ELEMENT(specification = Absyn.COMPONENTS(components = comps))
8620 algorithm
8621 ✗ for c in comps loop
8622 ✗ opt_mod := c.component.modification;
8623 ✗ mod := if isSome(opt_mod) then Util.getOption(opt_mod) else Absyn.emptyMod;
8624 ✗ vals := Values.Value.CODE(Absyn.CodeNode.C_MODIFICATION(mod)) :: vals;
8625 end for;
8626
8627 ✗ vals := Dangerous.listReverseInPlace(vals);
8628 ✗ then
8629 ValuesMake.makeArray(vals);
8630
8631 ✗ else ValuesMake.makeEmptyArray();
8632 end match;
8633 end getComponentModification;
8634
8635 public function cacheProgramAndPath
8636 input GraphicEnvCache inCache;
8637 output Absyn.Program outProgram;
8638 output Absyn.Path outPath;
8639 algorithm
8640 (outProgram, outPath) := match inCache
8641 7098 case GRAPHIC_ENV_FULL_CACHE() then (inCache.program, inCache.modelPath);
8642 ✗ case GRAPHIC_ENV_PARTIAL_CACHE() then (inCache.program, inCache.modelPath);
8643 10 case GRAPHIC_ENV_NO_CACHE() then (inCache.program, inCache.modelPath);
8644 end match;
8645 end cacheProgramAndPath;
8646
8647 public function envFromGraphicEnvCache
8648 input GraphicEnvCache inEnvCache;
8649 output FCore.Graph env;
8650 algorithm
8651 ✗ GRAPHIC_ENV_FULL_CACHE(env = env) := inEnvCache;
8652 end envFromGraphicEnvCache;
8653
8654 protected function cacheFromGraphicEnvCache
8655 input GraphicEnvCache inEnvCache;
8656 output FCore.Cache cache;
8657 algorithm
8658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7098 times.
7098 GRAPHIC_ENV_FULL_CACHE(cache = cache) := inEnvCache;
8659 end cacheFromGraphicEnvCache;
8660
8661 protected function getAnnotationString
8662 "Renders an annotation as a string."
8663 input Absyn.Annotation inAnnotation;
8664 input Absyn.Class inClass;
8665 input Absyn.Program inFullProgram;
8666 input Absyn.Path inModelPath;
8667 output String outString;
8668 protected
8669 list<Absyn.ElementArg> el = {};
8670 algorithm
8671
8672
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 if Flags.isSet(Flags.NF_API) then
8673 try
8674 20 outString := NFApi.evaluateAnnotation(inFullProgram, inModelPath, inAnnotation);
8675 else
8676 ✗ outString := Dump.unparseAnnotation(inAnnotation) + " ";
8677 end try;
8678 20 return;
8679 end if;
8680
8681 outString := matchcontinue inAnnotation
8682 case Absyn.ANNOTATION(el)
8683 algorithm
8684 ✗ outString := listHead(InteractiveUtil.getElementitemsAnnotationsElArgs(el, FGraph.emptyGraph, inClass, GRAPHIC_ENV_NO_CACHE(inFullProgram, inModelPath), false));
8685 then
8686 outString;
8687
8688 // If we fail, just return the annotation as it is.
8689 ✗ else Dump.unparseAnnotation(inAnnotation) + " ";
8690 end matchcontinue;
8691 end getAnnotationString;
8692
8693 public function keywordReplaceable
8694 "Returns true if RedeclareKeywords contains replaceable."
8695 input Option<Absyn.RedeclareKeywords> inAbsynRedeclareKeywordsOption;
8696 output Boolean outBoolean;
8697 algorithm
8698 outBoolean:=
8699 match inAbsynRedeclareKeywordsOption
8700 case SOME(Absyn.REPLACEABLE()) then true;
8701 case SOME(Absyn.REDECLARE_REPLACEABLE()) then true;
8702 else false;
8703 end match;
8704 end keywordReplaceable;
8705
8706 protected function getComponentInfoOld
8707 " This function takes an `Element\' and returns a list of strings
8708 of comma separated values of the type and name and comment of
8709 the component, e.g. \'Resistor,R1, \"comment\"\'
8710 or \'Resistor,R1,\"comment1\",R2,\"comment2\"\'
8711 If Element is not a component, the empty string is returned"
8712 input Absyn.Element inElement;
8713 input GraphicEnvCache inEnv;
8714 output String componentName;
8715 output Absyn.Path typeName;
8716 output String comment;
8717 protected
8718 Absyn.ComponentItem comp;
8719 algorithm
8720 (componentName, typeName, comment) := match inElement
8721 case Absyn.ELEMENT(specification = Absyn.COMPONENTS(typeSpec = Absyn.TPATH(typeName, _), components = comp :: _))
8722 algorithm
8723 2 componentName := comp.component.name;
8724 2 typeName := InteractiveUtil.qualifyPath(inEnv, typeName);
8725 2 comment := InteractiveUtil.getComponentComment(comp, inElement);
8726 then
8727 (componentName, typeName, comment);
8728 end match;
8729 end getComponentInfoOld;
8730
8731 public function transformPathedClassInProgram
8732 "Transforms a referenced class in a program by applying the given function to it."
8733 input Absyn.Path inPath;
8734 input Absyn.Program inProgram;
8735 input FuncType inFunc;
8736 output Absyn.Program outProgram;
8737
8738 partial function FuncType
8739 input Absyn.Class inClass;
8740 output Absyn.Class outClass;
8741 end FuncType;
8742 algorithm
8743 outProgram := match inPath
8744 case Absyn.IDENT()
8745 28 then transformClassInProgram(inPath.name, inProgram, inFunc);
8746
8747 case Absyn.FULLYQUALIFIED()
8748 ✗ then transformPathedClassInProgram(inPath.path, inProgram, inFunc);
8749
8750 case Absyn.QUALIFIED()
8751 5 then transformClassInProgram(inPath.name, inProgram,
8752 function transformPathedClassInClass(inPath = inPath.path, inFunc = inFunc));
8753
8754 end match;
8755 end transformPathedClassInProgram;
8756
8757 public function transformClassInProgram
8758 "Transforms a referenced class in a program by applying the given function to
8759 it, replacing the old class with the new in the list of classes. Fails if the
8760 class can't be found."
8761 input String inName;
8762 input Absyn.Program inProgram;
8763 input FuncType inFunc;
8764 output Absyn.Program outProgram;
8765
8766 partial function FuncType
8767 input Absyn.Class inClass;
8768 output Absyn.Class outClass;
8769 end FuncType;
8770 protected
8771 list<Absyn.Class> classes, acc = {};
8772 Absyn.Within wi;
8773 Absyn.Class cls;
8774 String name;
8775 algorithm
8776 33 Absyn.PROGRAM(classes, wi) := inProgram;
8777
8778 7 while true loop
8779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 cls :: classes := classes;
8780 40 Absyn.CLASS(name = name) := cls;
8781
8782
3/4
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 7 times.
✓ Branch 3 taken 33 times.
✗ Branch 4 not taken.
40 if name == inName then
8783
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 cls := inFunc(cls);
8784 31 classes := List.append_reverse(acc, cls :: classes);
8785 31 outProgram := Absyn.PROGRAM(classes, wi);
8786 break;
8787 end if;
8788
8789 acc := cls :: acc;
8790 end while;
8791 end transformClassInProgram;
8792
8793 protected function transformPathedClassInClass
8794 input Absyn.Path inPath;
8795 input Absyn.Class inClass;
8796 input FuncType inFunc;
8797 output Absyn.Class outClass;
8798
8799 partial function FuncType
8800 input Absyn.Class inClass;
8801 output Absyn.Class outClass;
8802 end FuncType;
8803 algorithm
8804 outClass := match inPath
8805 case Absyn.Path.IDENT()
8806 5 then transformClassInClass(inPath.name, inFunc, inClass);
8807
8808 case Absyn.Path.QUALIFIED()
8809 ✗ then transformClassInClass(inPath.name,
8810 function transformPathedClassInClass(inPath = inPath.path, inFunc = inFunc),
8811 inClass);
8812
8813 case Absyn.Path.FULLYQUALIFIED()
8814 ✗ then transformPathedClassInClass(inPath.path, inClass, inFunc);
8815
8816 end match;
8817 end transformPathedClassInClass;
8818
8819 function transformClassInClass
8820 input String name;
8821 input FuncType func;
8822 input output Absyn.Class cls;
8823
8824 partial function FuncType
8825 input output Absyn.Class cls;
8826 end FuncType;
8827 protected
8828 Absyn.ClassDef body = cls.body;
8829 algorithm
8830 () := match body
8831 case Absyn.ClassDef.PARTS()
8832 algorithm
8833 10 body.classParts := List.findMap(body.classParts,
8834 function transformClassInClassPart(name = name, func = func));
8835 then
8836 ();
8837
8838 case Absyn.ClassDef.CLASS_EXTENDS()
8839 algorithm
8840 ✗ body.parts := List.findMap(body.parts,
8841 function transformClassInClassPart(name = name, func = func));
8842 then
8843 ();
8844
8845 else ();
8846 end match;
8847
8848 5 cls.body := body;
8849 end transformClassInClass;
8850
8851 function transformClassInClassPart
8852 input String name;
8853 input FuncType func;
8854 input output Absyn.ClassPart part;
8855 output Boolean found;
8856
8857 partial function FuncType
8858 input output Absyn.Class cls;
8859 end FuncType;
8860 algorithm
8861 found := match part
8862 local
8863 list<Absyn.ElementItem> items;
8864
8865 case Absyn.ClassPart.PUBLIC()
8866 algorithm
8867 5 (items, found) := List.findMap(part.contents,
8868 function transformClassInElementItem(name = name, func = func));
8869 5 part.contents := items;
8870 5 then
8871 found;
8872
8873 case Absyn.ClassPart.PROTECTED()
8874 algorithm
8875 ✗ (items, found) := List.findMap(part.contents,
8876 function transformClassInElementItem(name = name, func = func));
8877 ✗ part.contents := items;
8878 ✗ then
8879 found;
8880
8881 else false;
8882 end match;
8883 end transformClassInClassPart;
8884
8885 function transformClassInElementItem
8886 input String name;
8887 input FuncType func;
8888 input output Absyn.ElementItem item;
8889 output Boolean found;
8890
8891 partial function FuncType
8892 input output Absyn.Class cls;
8893 end FuncType;
8894 algorithm
8895 found := match item
8896 local
8897 Absyn.Element e;
8898
8899 case Absyn.ElementItem.ELEMENTITEM()
8900 algorithm
8901 5 (e, found) := transformClassInElement(name, func, item.element);
8902 5 item.element := e;
8903 5 then
8904 found;
8905
8906 else false;
8907 end match;
8908 end transformClassInElementItem;
8909
8910 function transformClassInElement
8911 input String name;
8912 input FuncType func;
8913 input output Absyn.Element element;
8914 output Boolean found;
8915
8916 partial function FuncType
8917 input output Absyn.Class cls;
8918 end FuncType;
8919 algorithm
8920 found := match element
8921 local
8922 Absyn.ElementSpec spec;
8923
8924 case Absyn.Element.ELEMENT()
8925 algorithm
8926 5 (spec, found) := transformClassInElementSpec(name, func, element.specification);
8927 5 element.specification := spec;
8928 5 then
8929 found;
8930
8931 else false;
8932 end match;
8933 end transformClassInElement;
8934
8935 function transformClassInElementSpec
8936 input String name;
8937 input FuncType func;
8938 input output Absyn.ElementSpec spec;
8939 output Boolean found;
8940
8941 partial function FuncType
8942 input output Absyn.Class cls;
8943 end FuncType;
8944 algorithm
8945 found := match spec
8946 local
8947 Absyn.Class cls;
8948
8949 case Absyn.ElementSpec.CLASSDEF(class_ = cls)
8950 guard cls.name == name
8951 algorithm
8952
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 spec.class_ := func(cls);
8953 then
8954 true;
8955
8956 else false;
8957 end match;
8958 end transformClassInElementSpec;
8959
8960 public function getContainedClassAndFile
8961 " author: PA
8962 Returns the package or class in which the model is saved and the file
8963 name it is saved in. This is used to save a model in a package when the
8964 whole package is saved in a file.
8965 inputs: (Absyn.Path, Absyn.Program)
8966 outputs: (Absyn.Program, string /* filename */)"
8967 input Absyn.Path inPath;
8968 input Absyn.Program inProgram;
8969 output Absyn.Program outProgram;
8970 output String outString;
8971 algorithm
8972 (outProgram,outString):=
8973 match (inPath,inProgram)
8974 local
8975 Absyn.Class cdef;
8976 String filename;
8977 Absyn.Program p_1,p_2,p;
8978 Absyn.Path classname;
8979 case (classname,p)
8980 algorithm
8981 ✗ cdef := ProgramUtil.getPathedClassInProgram(classname, p);
8982 ✗ filename := AbsynUtil.classFilename(cdef);
8983 ✗ p_1 := getSurroundingPackage(classname, p);
8984 ✗ p_2 := removeInnerDiffFiledClasses(p_1);
8985 then
8986 (p_2,filename);
8987 end match;
8988 end getContainedClassAndFile;
8989
8990 protected function removeInnerDiffFiledClasses
8991 " author: PA
8992 Removes all inner classes that have different file name than the class
8993 itself. The filename of the class is passed as argument.
8994 inputs: (Absyn.Program /* package as program. */)
8995 outputs: Absyn.Program"
8996 input Absyn.Program inProgram;
8997 output Absyn.Program p = inProgram;
8998 algorithm
8999 p := match p
9000 case Absyn.PROGRAM()
9001 algorithm
9002 ✗ p.classes := List.map(p.classes, removeInnerDiffFiledClass);
9003 then p;
9004 end match;
9005 end removeInnerDiffFiledClasses;
9006
9007 protected function removeInnerDiffFiledClass
9008 " author: PA
9009 Helper function to removeInnerDiffFiledClasses, removes all local
9010 classes in class that does not have the same filename as the class
9011 iteself."
9012 input Absyn.Class inClass;
9013 output Absyn.Class outClass;
9014 algorithm
9015 outClass:=
9016 match inClass
9017 local
9018 list<Absyn.ElementItem> publst,publst2;
9019 list<Absyn.ClassPart> parts2,parts;
9020 String file,baseClassName;
9021 Option<String> cmt;
9022 list<Absyn.ElementArg> modifications;
9023 list<String> typeVars;
9024 list<Absyn.NamedArg> classAttrs;
9025 list<Absyn.Annotation> ann;
9026
9027 case outClass as Absyn.CLASS(
9028 body = Absyn.PARTS(typeVars = typeVars, classAttrs = classAttrs, classParts = parts,ann = ann,comment = cmt),
9029 info = (SOURCEINFO(fileName = file)))
9030 algorithm
9031 ✗ publst := ProgramUtil.getPublicList(parts);
9032 ✗ publst2 := removeClassDiffFiledInElementitemlist(publst, file);
9033 ✗ parts2 := ProgramUtil.replacePublicList(parts, publst2);
9034 ✗ outClass.body := Absyn.PARTS(typeVars,classAttrs,parts2,ann,cmt);
9035 then
9036 outClass;
9037
9038 /* adrpo: handle also the case model extends X end X; */
9039 case outClass as Absyn.CLASS(
9040 body = Absyn.CLASS_EXTENDS(baseClassName=baseClassName,
9041 modifications = modifications,
9042 parts = parts,
9043 ann = ann,
9044 comment = cmt),
9045 info = (SOURCEINFO(fileName = file)))
9046 algorithm
9047 ✗ publst := ProgramUtil.getPublicList(parts);
9048 ✗ publst2 := removeClassDiffFiledInElementitemlist(publst, file);
9049 ✗ parts2 := ProgramUtil.replacePublicList(parts, publst2);
9050 ✗ outClass.body := Absyn.CLASS_EXTENDS(baseClassName,modifications,cmt,parts2,ann);
9051 then
9052 outClass;
9053 // Short class definitions, etc
9054 else inClass;
9055 end match;
9056 end removeInnerDiffFiledClass;
9057
9058 protected function classIsInFile
9059 "returns true for the class that has the given filename
9060 returns true for anything else which does not have a filename"
9061 input String inFilename;
9062 input Absyn.ElementItem inElement;
9063 output Boolean outInFile;
9064 algorithm
9065 outInFile := match inElement
9066 local
9067 String filename;
9068
9069 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification =
9070 Absyn.CLASSDEF(class_ = Absyn.CLASS(info = SOURCEINFO(fileName = filename)))))
9071 ✗ then stringEq(inFilename, filename);
9072
9073 else true;
9074
9075 end match;
9076 end classIsInFile;
9077
9078 protected function removeClassDiffFiledInElementitemlist
9079 "author: PA
9080 This function takes an Element list and a filename
9081 and returns a modified element list where the elements
9082 not stored in filename are removed.
9083 inputs: (Absyn.ElementItem list, string /* filename */)
9084 outputs: Absyn.ElementItem list"
9085 input list<Absyn.ElementItem> inElements;
9086 input String inFilename;
9087 output list<Absyn.ElementItem> outElements;
9088 algorithm
9089 ✗ outElements := List.filterOnTrue(inElements,
9090 function classIsInFile(inFilename = inFilename));
9091 end removeClassDiffFiledInElementitemlist;
9092
9093 protected function getSurroundingPackage
9094 " author: PA
9095 This function investigates the surrounding packages and returns
9096 the outermost package that has the same filename as the class"
9097 input Absyn.Path classpath;
9098 input Absyn.Program inProgram;
9099 output Absyn.Program p = inProgram;
9100 algorithm
9101 p := matchcontinue p
9102 local
9103 Absyn.Class cdef,pdef;
9104 String filename1,filename2;
9105 Absyn.Path ppath;
9106 Absyn.Program res;
9107 Absyn.Within within_;
9108
9109 case _
9110 algorithm
9111 ✗ cdef := ProgramUtil.getPathedClassInProgram(classpath, p);
9112 ✗ filename1 := AbsynUtil.classFilename(cdef);
9113 ✗ ppath := AbsynUtil.stripLast(classpath);
9114 ✗ pdef := ProgramUtil.getPathedClassInProgram(ppath, p);
9115 ✗ filename2 := AbsynUtil.classFilename(pdef);
9116 ✗ true := stringEq(filename1, filename2);
9117 ✗ res := getSurroundingPackage(ppath, p);
9118 then
9119 res;
9120
9121 /* No package with same filename */
9122 case Absyn.PROGRAM()
9123 algorithm
9124 ✗ p.classes := {ProgramUtil.getPathedClassInProgram(classpath, p)};
9125 ✗ p.within_ := ProgramUtil.buildWithin(classpath);
9126 then p;
9127 end matchcontinue;
9128 end getSurroundingPackage;
9129
9130 public function transformFlatProgram
9131 "Transforms component references in a Absyn.PROGRAM
9132 to same format as the variables of the flat program.
9133 i.e. a.b[3].c[2] becomes CREF_IDENT(\"a.b[3].c\",[INDEX(ICONST(2))])"
9134 input Absyn.Program p;
9135 output Absyn.Program newP;
9136 algorithm
9137 newP := match p
9138 case _ algorithm
9139 ✗ (newP,_,_) := AbsynUtil.traverseClasses(p,NONE(), transformFlatClass, 0, true) "traverse protected" ;
9140 then newP;
9141 end match;
9142 end transformFlatProgram;
9143
9144 protected function transformFlatClass
9145 "This is the visitor function for traversing a class in transformFlatProgram."
9146 input tuple<Absyn.Class, Option<Absyn.Path>,Integer > inTuple;
9147 output tuple<Absyn.Class, Option<Absyn.Path>, Integer> outTuple;
9148 algorithm
9149 outTuple:= matchcontinue inTuple
9150 local
9151 Option<Absyn.Path> pa;
9152 Absyn.ClassDef cdef,cdef1;
9153 Integer i;
9154 Absyn.Class cl;
9155
9156 case (cl as Absyn.CLASS(body=cdef),pa,i)
9157 algorithm
9158 ✗ cdef1 := transformFlatClassDef(cdef);
9159 ✗ cl.body := cdef1;
9160 ✗ then ((cl,pa,i));
9161
9162 else
9163 algorithm
9164 ✗ print("Interactive.transformFlatClass failed\n");
9165 ✗ then fail();
9166 end matchcontinue;
9167 end transformFlatClass;
9168
9169 protected function transformFlatClassDef
9170 "Help function to transformFlatClass."
9171 input Absyn.ClassDef cdef;
9172 output Absyn.ClassDef outCdef;
9173 algorithm
9174 outCdef := matchcontinue cdef
9175 local
9176 list<Absyn.ClassPart> parts,partsTransformed;
9177 String baseClassName;
9178 list<Absyn.ElementArg> modifications;
9179 Option<String> cmt;
9180 list<String> typeVars;
9181 list<Absyn.NamedArg> classAttrs;
9182 list<Absyn.Annotation> ann;
9183 case Absyn.DERIVED() then cdef;
9184 case Absyn.ENUMERATION() then cdef;
9185 case Absyn.OVERLOAD() then cdef;
9186 case Absyn.PDER() then cdef;
9187 case Absyn.PARTS(typeVars,classAttrs,parts,ann,cmt)
9188 algorithm
9189 ✗ partsTransformed := List.map(parts,transformFlatPart);
9190 ✗ then
9191 Absyn.PARTS(typeVars,classAttrs,partsTransformed,ann,cmt);
9192 /*
9193 * adrpo: TODO! are we sure we shouldn't handle also the parts in model extends X parts end X; ??!!
9194 how about the modifications also??
9195 * before it was: case (cdef as Absyn.CLASS_EXTENDS(baseClassName = _) then cdef;
9196 */
9197 case Absyn.CLASS_EXTENDS(baseClassName = baseClassName,
9198 modifications = modifications,
9199 comment = cmt,
9200 ann = ann,
9201 parts = parts)
9202 algorithm
9203 ✗ partsTransformed := List.map(parts,transformFlatPart);
9204 ✗ then
9205 Absyn.CLASS_EXTENDS(baseClassName, modifications, cmt, partsTransformed, ann);
9206 ✗ else algorithm print("Interactive.transformFlatClassDef failed\n");
9207 ✗ then fail();
9208 end matchcontinue;
9209 end transformFlatClassDef;
9210
9211 public function transformFlatPart
9212 "Help function to transformFlatClassDef."
9213 input Absyn.ClassPart part;
9214 output Absyn.ClassPart outPart;
9215 algorithm
9216 outPart := matchcontinue part
9217 local
9218 list<Absyn.ElementItem> eitems, eitems1;
9219 list<Absyn.EquationItem> eqnitems, eqnitems1;
9220 list<Absyn.AlgorithmItem> algitems,algitems1;
9221 case Absyn.PUBLIC(eitems)
9222 algorithm
9223 ✗ eitems1 := List.map(eitems,transformFlatElementItem);
9224 ✗ then Absyn.PUBLIC(eitems1);
9225 case Absyn.PROTECTED(eitems)
9226 algorithm
9227 ✗ eitems1 := List.map(eitems,transformFlatElementItem);
9228 ✗ then Absyn.PROTECTED(eitems1);
9229 case Absyn.EQUATIONS(eqnitems)
9230 algorithm
9231 ✗ eqnitems1 := List.map(eqnitems,transformFlatEquationItem);
9232 ✗ then Absyn.EQUATIONS(eqnitems1);
9233 case Absyn.INITIALEQUATIONS(eqnitems)
9234 algorithm
9235 ✗ eqnitems1 := List.map(eqnitems,transformFlatEquationItem);
9236 ✗ then Absyn.INITIALEQUATIONS(eqnitems1);
9237 case Absyn.ALGORITHMS(algitems)
9238 algorithm
9239 ✗ algitems1 := List.map(algitems,transformFlatAlgorithmItem);
9240 ✗ then Absyn.ALGORITHMS(algitems1);
9241 case Absyn.INITIALALGORITHMS(algitems)
9242 algorithm
9243 ✗ algitems1 := List.map(algitems,transformFlatAlgorithmItem);
9244 ✗ then Absyn.INITIALALGORITHMS(algitems1);
9245 case Absyn.EXTERNAL(_,_) then part;
9246 else
9247 ✗ algorithm print("Interactive.transformFlatPart failed\n");
9248 ✗ then fail();
9249 end matchcontinue;
9250 end transformFlatPart;
9251
9252 protected function transformFlatElementItem
9253 "Help function to transformFlatParts"
9254 input Absyn.ElementItem eitem;
9255 output Absyn.ElementItem outEitem;
9256 algorithm
9257 outEitem := match eitem
9258 local Absyn.Element elt,elt1;
9259 ✗ case Absyn.ELEMENTITEM(elt) algorithm elt1 := transformFlatElement(elt); then (Absyn.ELEMENTITEM(elt1));
9260 end match;
9261 end transformFlatElementItem;
9262
9263 protected function transformFlatElement
9264 "Help function to transformFlatElementItem"
9265 input Absyn.Element elt;
9266 output Absyn.Element outElt;
9267 algorithm
9268 outElt := match elt
9269 local
9270 Boolean f;
9271 Option<Absyn.RedeclareKeywords> r;
9272 Absyn.InnerOuter io;
9273 Absyn.ElementSpec spec,spec1;
9274 SourceInfo info ;
9275 Option<Absyn.ConstrainClass> constr;
9276 case Absyn.TEXT() then elt;
9277 case Absyn.ELEMENT(f,r,io,spec,info,constr)
9278 algorithm
9279 ✗ spec1:=transformFlatElementSpec(spec);
9280 //TODO: constr clause might need transformation too.
9281 ✗ then
9282 Absyn.ELEMENT(f,r,io,spec1,info,constr);
9283 end match;
9284 end transformFlatElement;
9285
9286 protected function transformFlatElementSpec
9287 "Helper to transformFlatElement"
9288 input Absyn.ElementSpec eltSpec;
9289 output Absyn.ElementSpec outEltSpec;
9290 algorithm
9291 outEltSpec := match eltSpec
9292 local
9293 Boolean r;
9294 Absyn.Class cl,cl1;
9295 Absyn.Path path;
9296 Absyn.TypeSpec tp;
9297 list<Absyn.ElementArg> eargs,eargs1;
9298 Absyn.ElementAttributes attr;
9299 list<Absyn.ComponentItem> comps,comps1;
9300 Option<Absyn.Annotation> annOpt;
9301
9302 case Absyn.CLASSDEF(r,cl)
9303 algorithm
9304 ✗ (cl1,_,_) := transformFlatClass((cl,NONE(),0));
9305 ✗ then Absyn.CLASSDEF(r,cl1);
9306
9307 case Absyn.EXTENDS(path,eargs,annOpt)
9308 algorithm
9309 ✗ eargs1 := List.map(eargs,transformFlatElementArg);
9310 ✗ then Absyn.EXTENDS(path,eargs1,annOpt);
9311
9312 case Absyn.IMPORT() then eltSpec;
9313
9314 case Absyn.COMPONENTS(attr,tp,comps)
9315 algorithm
9316 ✗ comps1 := List.map(comps,transformFlatComponentItem);
9317 ✗ then Absyn.COMPONENTS(attr,tp,comps1);
9318
9319 end match;
9320 end transformFlatElementSpec;
9321
9322 protected function transformFlatComponentItem
9323 "Help function to transformFlatElementSpec"
9324 input Absyn.ComponentItem compitem;
9325 output Absyn.ComponentItem outCompitem;
9326 algorithm
9327 outCompitem := match compitem
9328 local
9329 Option<Absyn.ComponentCondition> cond;
9330 Option<Absyn.Comment> cmt;
9331 Absyn.Component comp,compTransformed;
9332 case Absyn.COMPONENTITEM(comp,cond,cmt)
9333 algorithm
9334 ✗ compTransformed := transformFlatComponent(comp);
9335 ✗ then
9336 Absyn.COMPONENTITEM(compTransformed,cond,cmt);
9337 end match;
9338 end transformFlatComponentItem;
9339
9340 protected function transformFlatComponent
9341 "Help function to transformFlatComponentItem"
9342 input Absyn.Component comp;
9343 output Absyn.Component outComp;
9344 algorithm
9345 outComp := match comp
9346 local
9347 Absyn.ArrayDim arraydim,arraydimTransformed;
9348 Option<Absyn.Modification> mod,modTransformed;
9349 Absyn.Ident id;
9350 case Absyn.COMPONENT(id,arraydim,mod)
9351 algorithm
9352 ✗ modTransformed := transformFlatModificationOption(mod);
9353 ✗ arraydimTransformed := transformFlatArrayDim(arraydim);
9354 ✗ then
9355 Absyn.COMPONENT(id,arraydimTransformed,modTransformed);
9356 end match;
9357 end transformFlatComponent;
9358
9359 protected function transformFlatArrayDim
9360 "Help function to transformFlatComponent"
9361 input Absyn.ArrayDim ad;
9362 output Absyn.ArrayDim outAd;
9363 algorithm
9364 ✗ outAd := match ad
9365 local Absyn.ArrayDim adTransformed;
9366 case _
9367 algorithm
9368 adTransformed := List.map(ad,transformFlatSubscript);
9369 then adTransformed;
9370 end match;
9371 end transformFlatArrayDim;
9372
9373 protected function transformFlatSubscript
9374 "Help function to TransformFlatArrayDim"
9375 input Absyn.Subscript s;
9376 output Absyn.Subscript outS;
9377 algorithm
9378 outS := match s
9379 local Absyn.Exp e,e1;
9380 case Absyn.NOSUB() then Absyn.NOSUB();
9381 case Absyn.SUBSCRIPT(e)
9382 algorithm
9383 ✗ (e1,_) := AbsynUtil.traverseExp(e,transformFlatExp,0);
9384 ✗ then
9385 Absyn.SUBSCRIPT(e1);
9386 end match;
9387 end transformFlatSubscript;
9388
9389 protected function transformFlatElementArg
9390 "Helper function to e.g. transformFlatElementSpec"
9391 input Absyn.ElementArg eltArg;
9392 output Absyn.ElementArg outEltArg;
9393 algorithm
9394 outEltArg := match eltArg
9395 local
9396 Boolean f;
9397 Absyn.Each e;
9398 Option<Absyn.Modification> mod,mod1;
9399 Option<String> cmt;
9400 SourceInfo info;
9401 Absyn.Path p;
9402
9403 case Absyn.MODIFICATION(f,e,p,mod,cmt,info)
9404 algorithm
9405 ✗ mod1 := transformFlatModificationOption(mod);
9406 ✗ then
9407 Absyn.MODIFICATION(f,e,p,mod1,cmt,info);
9408 // redeclarations not in flat Modelica
9409 case Absyn.REDECLARATION()
9410 then eltArg;
9411 end match;
9412 end transformFlatElementArg;
9413
9414 protected function transformFlatModificationOption
9415 "Help function to transformFlatElementArg"
9416 input Option<Absyn.Modification> mod;
9417 output Option<Absyn.Modification> outMod;
9418 algorithm
9419 outMod := match mod
9420 local
9421 SourceInfo info;
9422 Absyn.Exp e,e1;
9423 list<Absyn.ElementArg> eltArgs,eltArgs1;
9424 case SOME(Absyn.CLASSMOD(eltArgs,Absyn.EQMOD(e,info)))
9425 algorithm
9426 ✗ eltArgs1:=List.map(eltArgs,transformFlatElementArg);
9427 ✗ (e1,_) := AbsynUtil.traverseExp(e,transformFlatExp,0);
9428 ✗ then SOME(Absyn.CLASSMOD(eltArgs1,Absyn.EQMOD(e1,info)));
9429 case SOME(Absyn.CLASSMOD(eltArgs,Absyn.NOMOD()))
9430 algorithm
9431 ✗ eltArgs1:=List.map(eltArgs,transformFlatElementArg);
9432 ✗ then SOME(Absyn.CLASSMOD(eltArgs1,Absyn.NOMOD()));
9433 case NONE() then NONE();
9434 end match;
9435 end transformFlatModificationOption;
9436
9437 protected function transformFlatComponentRef
9438 "Help function to e.g. transformFlatElementArg and transformFlatExp"
9439 input Absyn.ComponentRef cr;
9440 output Absyn.ComponentRef outCr;
9441 algorithm
9442 outCr := match cr
9443 local Absyn.ComponentRef cr1;
9444 list<Absyn.Subscript> ss;
9445 String s;
9446 case _ algorithm
9447 ✗ ss := AbsynUtil.crefLastSubs(cr);
9448 ✗ cr1 := AbsynUtil.crefStripLastSubs(cr);
9449 ✗ s := Dump.printComponentRefStr(cr1);
9450 ✗ then Absyn.CREF_IDENT(s,ss);
9451 end match;
9452 end transformFlatComponentRef;
9453
9454 protected function transformFlatEquationItem
9455 "Help function to transformFlatParts"
9456 input Absyn.EquationItem eqnitem;
9457 output Absyn.EquationItem outEqnitem;
9458 algorithm
9459 outEqnitem := match eqnitem
9460 local
9461 Option<Absyn.Comment> cmt;
9462 Absyn.Equation eqn,eqn1;
9463 SourceInfo info;
9464 case Absyn.EQUATIONITEM(eqn,cmt,info)
9465 algorithm
9466 ✗ eqn1 := transformFlatEquation(eqn);
9467 ✗ then Absyn.EQUATIONITEM(eqn1,cmt,info);
9468 end match;
9469 end transformFlatEquationItem;
9470
9471 protected function transformFlatEquation
9472 "Help function to transformFlatEquationItem"
9473 input Absyn.Equation eqn;
9474 output Absyn.Equation outEqn;
9475 algorithm
9476 outEqn := match eqn
9477 local
9478 Absyn.Exp e1,e2,e11,e21;
9479 Absyn.Ident id;
9480 Absyn.ComponentRef name;
9481 list<Absyn.EquationItem> thenpart,thenpart1,elsepart,elsepart1,forEqns,forEqns1,whenEqns,whenEqns1;
9482 list<tuple<Absyn.Exp,list<Absyn.EquationItem>>> elseifpart,elseifpart1,elseWhenEqns,elseWhenEqns1;
9483 Absyn.ComponentRef cr1,cr2,cr11,cr21;
9484 Absyn.FunctionArgs fargs,fargs1;
9485
9486 case Absyn.EQ_IF(e1,thenpart,elseifpart,elsepart)
9487 algorithm
9488 ✗ (e11,_) := AbsynUtil.traverseExp(e1,transformFlatExp,0);
9489 ✗ thenpart1 := List.map(thenpart,transformFlatEquationItem);
9490 ✗ elsepart1 := List.map(elsepart,transformFlatEquationItem);
9491 ✗ elseifpart1 := List.map(elseifpart,transformFlatElseIfPart);
9492 ✗ then
9493 Absyn.EQ_IF(e11,thenpart1,elseifpart1,elsepart1);
9494
9495 case Absyn.EQ_EQUALS(e1,e2)
9496 algorithm
9497 ✗ (e11,_) := AbsynUtil.traverseExp(e1,transformFlatExp,0);
9498 ✗ (e21,_) := AbsynUtil.traverseExp(e2,transformFlatExp,0);
9499 ✗ then
9500 Absyn.EQ_EQUALS(e11,e21);
9501
9502 case Absyn.EQ_PDE(e1,e2,cr1)
9503 algorithm
9504 ✗ (e11,_) := AbsynUtil.traverseExp(e1,transformFlatExp,0);
9505 ✗ (e21,_) := AbsynUtil.traverseExp(e2,transformFlatExp,0);
9506 ✗ cr11 := transformFlatComponentRef(cr1);
9507 ✗ then
9508 Absyn.EQ_PDE(e11,e21,cr11);
9509
9510 case Absyn.EQ_CONNECT(cr1,cr2)
9511 algorithm
9512 ✗ cr11 := transformFlatComponentRef(cr1);
9513 ✗ cr21 := transformFlatComponentRef(cr2);
9514 ✗ then
9515 Absyn.EQ_CONNECT(cr11,cr21);
9516
9517 case Absyn.EQ_FOR({Absyn.ITERATOR(id,NONE(),SOME(e1))},forEqns)
9518 algorithm
9519 ✗ (e11,_) := AbsynUtil.traverseExp(e1,transformFlatExp,0);
9520 ✗ forEqns1 := List.map(forEqns,transformFlatEquationItem);
9521 ✗ then
9522 Absyn.EQ_FOR({Absyn.ITERATOR(id,NONE(),SOME(e11))},forEqns1);
9523
9524 case Absyn.EQ_WHEN_E(e1,whenEqns,elseWhenEqns)
9525 algorithm
9526 ✗ (e11,_) := AbsynUtil.traverseExp(e1,transformFlatExp,0);
9527 ✗ elseWhenEqns1 := List.map(elseWhenEqns,transformFlatElseIfPart);
9528 ✗ whenEqns1 := List.map(whenEqns,transformFlatEquationItem);
9529 ✗ then
9530 Absyn.EQ_WHEN_E(e11,whenEqns1,elseWhenEqns1);
9531
9532 case Absyn.EQ_NORETCALL(name,fargs)
9533 algorithm
9534 ✗ fargs1 := transformFlatFunctionArgs(fargs);
9535 ✗ then
9536 Absyn.EQ_NORETCALL(name,fargs1);
9537 end match;
9538 end transformFlatEquation;
9539
9540 protected function transformFlatElseIfPart
9541 "Help function to transformFlatEquation"
9542 input tuple<Absyn.Exp, list<Absyn.EquationItem>> elseIfPart;
9543 output tuple<Absyn.Exp, list<Absyn.EquationItem>> outElseIfPart;
9544 algorithm
9545 outElseIfPart := match elseIfPart
9546 local
9547 Absyn.Exp e1,e11;
9548 list<Absyn.EquationItem> eqnitems,eqnitems1;
9549 case (e1,eqnitems)
9550 algorithm
9551 ✗ (e11,_) := AbsynUtil.traverseExp(e1,transformFlatExp,0);
9552 ✗ eqnitems1 := List.map(eqnitems,transformFlatEquationItem);
9553 ✗ then
9554 ((e11,eqnitems1));
9555 end match;
9556 end transformFlatElseIfPart;
9557
9558 protected function transformFlatFunctionArgs
9559 "Help function to e.g. transformFlatEquation"
9560 input Absyn.FunctionArgs fargs;
9561 output Absyn.FunctionArgs outFargs;
9562 algorithm
9563 outFargs := match fargs
9564 local
9565 list<Absyn.Exp> expl,expl1;
9566 list<Absyn.NamedArg> namedArgs,namedArgs1;
9567 case Absyn.FUNCTIONARGS(expl,namedArgs)
9568 algorithm
9569 ✗ expl1 := list(AbsynUtil.traverseExp(e, transformFlatExp, 0) for e in expl);
9570 ✗ namedArgs1 := List.map(namedArgs,transformFlatNamedArg);
9571 ✗ then
9572 Absyn.FUNCTIONARGS(expl1,namedArgs1);
9573 case Absyn.FOR_ITER_FARG()
9574 then fargs;
9575 end match;
9576 end transformFlatFunctionArgs;
9577
9578 protected function transformFlatNamedArg
9579 "Helper functin to e.g. transformFlatFunctionArgs"
9580 input Absyn.NamedArg namedArg;
9581 output Absyn.NamedArg outNamedArg;
9582 algorithm
9583 outNamedArg := match namedArg
9584 local Absyn.Exp e1,e11; Absyn.Ident id;
9585 case Absyn.NAMEDARG(id,e1)
9586 algorithm
9587 ✗ (e11,_) := AbsynUtil.traverseExp(e1,transformFlatExp,0);
9588 ✗ then Absyn.NAMEDARG(id,e11);
9589 end match;
9590 end transformFlatNamedArg;
9591
9592 protected function transformFlatExp
9593 input Absyn.Exp inExp;
9594 input Integer inDummy;
9595 output Absyn.Exp outExp;
9596 output Integer outDummy;
9597 algorithm
9598 (outExp,outDummy) := matchcontinue(inExp,inDummy)
9599 local
9600 Absyn.ComponentRef cr,cr1;
9601 Integer i;
9602 case (Absyn.CREF(cr),i)
9603 algorithm
9604 ✗ cr1 := transformFlatComponentRef(cr);
9605 ✗ then (Absyn.CREF(cr1),i);
9606 else (inExp,inDummy);
9607 end matchcontinue;
9608 end transformFlatExp;
9609
9610 protected function transformFlatAlgorithmItem
9611 input Absyn.AlgorithmItem algitem;
9612 output Absyn.AlgorithmItem outAlgitem;
9613 algorithm
9614 outAlgitem := match algitem
9615 local
9616 Option<Absyn.Comment> cmt;
9617 Absyn.Algorithm alg,alg1;
9618 SourceInfo info;
9619 case Absyn.ALGORITHMITEM(alg,cmt,info)
9620 algorithm
9621 ✗ alg1 := transformFlatAlgorithm(alg);
9622 ✗ then Absyn.ALGORITHMITEM(alg1,cmt,info);
9623 end match;
9624 end transformFlatAlgorithmItem;
9625
9626 protected function transformFlatAlgorithm
9627 "Help function to transformFlatAlgorithmItem"
9628 input Absyn.Algorithm alg;
9629 output Absyn.Algorithm outAlg;
9630 algorithm
9631 outAlg := match alg
9632 local Absyn.Exp e1,e11,e2,e21;
9633 Absyn.ComponentRef cr,cr1;
9634 list<Absyn.AlgorithmItem> body,body1,thenPart,thenPart1,elsePart,elsePart1;
9635 list<tuple<Absyn.Exp, list<Absyn.AlgorithmItem>>> elseIfPart,elseIfPart1,whenBranch,whenBranch1;
9636 Absyn.Ident id;
9637 Absyn.FunctionArgs fargs,fargs1;
9638 case Absyn.ALG_ASSIGN(Absyn.CREF(cr),e1)
9639 algorithm
9640 ✗ AbsynUtil.traverseExp(e1,transformFlatExp,0);
9641 ✗ cr1 := transformFlatComponentRef(cr);
9642 ✗ then
9643 Absyn.ALG_ASSIGN(Absyn.CREF(cr1),e1);
9644 case Absyn.ALG_ASSIGN(e1 as Absyn.TUPLE(_),e2)
9645 algorithm
9646 ✗ (e11,_) := AbsynUtil.traverseExp(e1,transformFlatExp,0);
9647 ✗ (e21,_) := AbsynUtil.traverseExp(e2,transformFlatExp,0);
9648 ✗ then
9649 Absyn.ALG_ASSIGN(e11,e21);
9650 case Absyn.ALG_IF(e1,thenPart,elseIfPart,elsePart)
9651 algorithm
9652 ✗ thenPart1 := List.map(thenPart,transformFlatAlgorithmItem);
9653 ✗ elseIfPart1 := List.map(elseIfPart,transformFlatElseIfAlgorithm);
9654 ✗ elsePart1 := List.map(elsePart,transformFlatAlgorithmItem);
9655 ✗ (e11,_) := AbsynUtil.traverseExp(e1,transformFlatExp,0);
9656 ✗ then
9657 Absyn.ALG_IF(e11,thenPart1,elseIfPart1,elsePart1);
9658 case Absyn.ALG_FOR({Absyn.ITERATOR(id,NONE(),SOME(e1))},body)
9659 algorithm
9660 ✗ (e11,_) := AbsynUtil.traverseExp(e1,transformFlatExp,0);
9661 ✗ body1 := List.map(body,transformFlatAlgorithmItem);
9662 ✗ then
9663 Absyn.ALG_FOR({Absyn.ITERATOR(id,NONE(),SOME(e11))},body1);
9664 case Absyn.ALG_WHILE(e1,body)
9665 algorithm
9666 ✗ (e11,_) := AbsynUtil.traverseExp(e1,transformFlatExp,0);
9667 ✗ body1 := List.map(body,transformFlatAlgorithmItem);
9668 ✗ then
9669 Absyn.ALG_WHILE(e11,body1);
9670 case Absyn.ALG_WHEN_A(e1,body,whenBranch)
9671 algorithm
9672 ✗ (e11,_) := AbsynUtil.traverseExp(e1,transformFlatExp,0);
9673 ✗ body1 := List.map(body,transformFlatAlgorithmItem);
9674 ✗ whenBranch1 := List.map(whenBranch,transformFlatElseIfAlgorithm);
9675 ✗ then
9676 Absyn.ALG_WHEN_A(e11,body1,whenBranch1);
9677 case Absyn.ALG_NORETCALL(cr,fargs)
9678 algorithm
9679 ✗ cr1 := transformFlatComponentRef(cr);
9680 ✗ fargs1 := transformFlatFunctionArgs(fargs);
9681 ✗ then
9682 Absyn.ALG_NORETCALL(cr1,fargs1);
9683 case Absyn.ALG_BREAK() then Absyn.ALG_BREAK();
9684 case Absyn.ALG_RETURN() then Absyn.ALG_RETURN();
9685
9686 end match;
9687 end transformFlatAlgorithm;
9688
9689 protected function transformFlatElseIfAlgorithm
9690 input tuple<Absyn.Exp, list<Absyn.AlgorithmItem>> elseIfbranch;
9691 output tuple<Absyn.Exp, list<Absyn.AlgorithmItem>> outElseIfbranch;
9692 algorithm
9693 outElseIfbranch := match elseIfbranch
9694 local
9695 Absyn.Exp e1,e11;
9696 list<Absyn.AlgorithmItem> algitems,algitems1;
9697 case (e1,algitems)
9698 algorithm
9699 ✗ (e11,_) := AbsynUtil.traverseExp(e1,transformFlatExp,0);
9700 ✗ algitems1 := List.map(algitems,transformFlatAlgorithmItem);
9701 ✗ then ((e11,algitems1));
9702 end match;
9703 end transformFlatElseIfAlgorithm;
9704
9705 /* Start getDefinitions */
9706
9707 public function getDefinitions
9708 "This function dumps the defined packages, classes and functions to a string.
9709 The function is used by org.openmodelica.corba.parser.DefinitionsCreator in the
9710 Java interface, which parses the string returned here. The corba in that package
9711 name is historical and does not imply a CORBA connection; OpenModelica no longer
9712 has a CORBA interface."
9713 input Absyn.Program ast "The AST to dump";
9714 input Boolean addFunctions;
9715 output Values.Value res "An easily parsed string containing all definitions";
9716 protected
9717 list<Absyn.Class> classes;
9718 Integer handle;
9719 Absyn.Class cl;
9720 algorithm
9721 ✗ Absyn.PROGRAM(classes = classes) := MetaUtil.createMetaClassesInProgram(ast);
9722 ✗ handle := Print.saveAndClearBuf();
9723 ✗ Print.printBuf("(\n");
9724
9725 ✗ for c in classes loop
9726 ✗ Print.printBuf(getDefinitionsClass(c, addFunctions));
9727 ✗ Print.printBufNewLine();
9728 end for;
9729
9730 ✗ cl := ProgramUtil.getPathedClassInProgram(Absyn.IDENT("SourceInfo"), ast);
9731 ✗ Print.printBuf(getDefinitionsClass(cl, false));
9732 ✗ Print.printBuf("\n\n)");
9733 ✗ res := ValuesMake.makeString(Print.getString());
9734 ✗ Print.restoreBuf(handle);
9735 end getDefinitions;
9736
9737 protected function getDefinitionsClass
9738 input Absyn.Class class_;
9739 input Boolean addFunctions;
9740 output String res;
9741 algorithm
9742 res := matchcontinue (class_,addFunctions)
9743 local
9744 String ident, tyStr;
9745 list<String> strs;
9746 Absyn.TypeSpec ts;
9747 Absyn.ElementAttributes attr;
9748 Integer numDim;
9749 Integer index;
9750 Absyn.Path path;
9751 String indexArg, pathArg;
9752 Absyn.ClassDef body;
9753
9754 case (Absyn.CLASS(name = ident, body = body as Absyn.PARTS(), restriction = Absyn.R_PACKAGE()),_)
9755 algorithm
9756 ✗ ident := "(package " + ident;
9757 ✗ strs := getDefinitionParts(body.classParts, body.typeVars, addFunctions);
9758 strs := ident :: strs;
9759 ✗ then stringDelimitList(strs, "\n");
9760 case (Absyn.CLASS(partialPrefix = true, name = ident, body = Absyn.PARTS(), restriction = Absyn.R_FUNCTION(Absyn.FR_NORMAL_FUNCTION(Absyn.IMPURE()))),_)
9761 algorithm
9762 strs := {"(partial impure function", ident, ")"};
9763 ✗ then stringDelimitList(strs, " ");
9764 case (Absyn.CLASS(partialPrefix = true, name = ident, body = Absyn.PARTS(), restriction = Absyn.R_FUNCTION(Absyn.FR_NORMAL_FUNCTION(_))),_)
9765 algorithm
9766 strs := {"(partial function", ident, ")"};
9767 ✗ then stringDelimitList(strs, " ");
9768 case (Absyn.CLASS(partialPrefix = false, name = ident, body = body as Absyn.PARTS(), restriction = Absyn.R_FUNCTION(Absyn.FR_NORMAL_FUNCTION(Absyn.IMPURE()))),true)
9769 algorithm
9770 ✗ strs := getDefinitionParts(body.classParts, body.typeVars, true);
9771 strs := "(impure function" :: ident :: strs;
9772 ✗ then stringDelimitList(strs, " ");
9773 case (Absyn.CLASS(partialPrefix = false, name = ident, body = body as Absyn.PARTS(), restriction = Absyn.R_FUNCTION(Absyn.FR_NORMAL_FUNCTION())),true)
9774 algorithm
9775 ✗ strs := getDefinitionParts(body.classParts, body.typeVars, true);
9776 strs := "(function" :: ident :: strs;
9777 ✗ then stringDelimitList(strs, " ");
9778 case (Absyn.CLASS(partialPrefix = false, name = ident, body = body as Absyn.PARTS(), restriction = Absyn.R_FUNCTION(Absyn.FR_OPERATOR_FUNCTION())),true)
9779 algorithm
9780 ✗ strs := getDefinitionParts(body.classParts, body.typeVars, true);
9781 strs := "(operator function" :: ident :: strs;
9782 ✗ then stringDelimitList(strs, " ");
9783 case (Absyn.CLASS(name = ident, body = Absyn.PARTS(), restriction = Absyn.R_UNIONTYPE()),_)
9784 algorithm
9785 strs := {"(uniontype", ident, ")"};
9786 ✗ then stringDelimitList(strs, " ");
9787 case (Absyn.CLASS(name = ident, body = body as Absyn.PARTS(), restriction = Absyn.R_RECORD()),_)
9788 algorithm
9789 ✗ strs := getDefinitionParts(body.classParts, body.typeVars, false);
9790 strs := "(record" :: ident :: strs;
9791 ✗ then stringDelimitList(strs, " ");
9792 case (Absyn.CLASS(name = ident, body = body as Absyn.PARTS(), restriction = Absyn.R_METARECORD(name = path, index = index)),_)
9793 algorithm
9794 ✗ indexArg := intString(index);
9795 ✗ pathArg := AbsynUtil.pathLastIdent(path);
9796 ✗ strs := getDefinitionParts(body.classParts, body.typeVars, false);
9797 strs := "(metarecord" :: ident :: indexArg :: pathArg :: strs;
9798 ✗ then stringDelimitList(strs, " ");
9799 case (Absyn.CLASS(name = ident, body = Absyn.DERIVED(typeSpec = ts, attributes = attr)),_)
9800 algorithm
9801 ✗ numDim := getDefinitionDimensions(ts,attr);
9802 ✗ tyStr := (if numDim == 0 then "" else "[" + intString(numDim)) + getDefinitionTypeSpecPathString(ts);
9803 strs := {"(type", ident, tyStr, ")"};
9804 ✗ then stringDelimitList(strs, " ");
9805 // Do enumerations really work properly in OMC?
9806 //case Absyn.CLASS(name = ident, body = Absyn.ENUMERATION(enumLiterals = Absyn.ENUMLITERALS(el))) equation
9807 // enumList = List.map(el, getEnumerationLiterals);
9808 //then "enumeration " + ident + "(" + stringDelimitList(enumList, ",") + ")";
9809 else "";
9810 end matchcontinue;
9811 end getDefinitionsClass;
9812
9813 protected function getDefinitionsReplaceableClass
9814 input Absyn.Class class_;
9815 output String res;
9816 algorithm
9817 res := match class_
9818 local
9819 String ident;
9820 case Absyn.CLASS(name = ident, body = Absyn.DERIVED(typeSpec = Absyn.TCOMPLEX(Absyn.IDENT("polymorphic"),{Absyn.TPATH(Absyn.IDENT("Any"),NONE())},NONE())), restriction = Absyn.R_TYPE())
9821 ✗ then "(replaceable type " + ident + ")";
9822 end match;
9823 end getDefinitionsReplaceableClass;
9824
9825 protected function getDefinitionPathString
9826 input Absyn.Path path;
9827 output String out;
9828 algorithm
9829 // Doesn't work because we only know the AST after parsing... case (Absyn.FULLYQUALIFIED(path)) then "#" + AbsynUtil.pathString(path);
9830 // Thus, scope/lookup is done by the application recieving this information
9831 ✗ out := AbsynUtil.pathString(path);
9832 end getDefinitionPathString;
9833
9834 public function getDefinitionTypeSpecPathString
9835 input Absyn.TypeSpec tp;
9836 output String s;
9837 algorithm s := matchcontinue tp
9838 local
9839 Absyn.Path p;
9840 list<Absyn.TypeSpec> tspecs;
9841 list<String> tspecsStr;
9842 case Absyn.TCOMPLEX(path = p, typeSpecs = {}) algorithm
9843 ✗ then getDefinitionPathString(p);
9844 case Absyn.TCOMPLEX(path = p, typeSpecs = tspecs) algorithm
9845 ✗ tspecsStr := List.map(tspecs, getDefinitionTypeSpecPathString);
9846 ✗ then getDefinitionPathString(p) + "<" + stringDelimitList(tspecsStr,",") + ">";
9847 ✗ case Absyn.TPATH(path = p) then getDefinitionPathString(p);
9848 end matchcontinue;
9849 end getDefinitionTypeSpecPathString;
9850
9851 protected function getDefinitionDimensions
9852 input Absyn.TypeSpec ts;
9853 input Absyn.ElementAttributes attr;
9854 output Integer out;
9855 algorithm
9856 out := match(ts,attr)
9857 local
9858 list<Absyn.Subscript> l1,l2;
9859 ✗ case (Absyn.TPATH(arrayDim = SOME(l1)), Absyn.ATTR(arrayDim = l2)) then listLength(l1)+listLength(l2);
9860 ✗ case (Absyn.TCOMPLEX(arrayDim = SOME(l1)), Absyn.ATTR(arrayDim = l2)) then listLength(l1)+listLength(l2);
9861 ✗ case (Absyn.TPATH(arrayDim = NONE()), Absyn.ATTR(arrayDim = l2)) then listLength(l2);
9862 ✗ case (Absyn.TCOMPLEX(arrayDim = NONE()), Absyn.ATTR(arrayDim = l2)) then listLength(l2);
9863 else 0;
9864 end match;
9865 end getDefinitionDimensions;
9866
9867 protected function getDefinitionParts
9868 input list<Absyn.ClassPart> parts;
9869 input list<String> inTypeVars;
9870 input Boolean isFunction;
9871 output list<String> res;
9872 algorithm
9873 res := matchcontinue parts
9874 local
9875 list<Absyn.ClassPart> rest;
9876 list<Absyn.ElementItem> contents;
9877 ✗ case {} then getDefinitionTypeVars(inTypeVars, {")"});
9878 case Absyn.PUBLIC(contents)::rest
9879 ✗ then listAppend(getDefinitionContent(contents,isFunction,true), getDefinitionParts(rest,inTypeVars,isFunction));
9880 case Absyn.PROTECTED(contents)::rest
9881 ✗ then listAppend(getDefinitionContent(contents,isFunction,false), getDefinitionParts(rest,inTypeVars, isFunction));
9882 ✗ case _::rest then getDefinitionParts(rest,inTypeVars,isFunction);
9883 end matchcontinue;
9884 end getDefinitionParts;
9885
9886 protected function getDefinitionContent
9887 input list<Absyn.ElementItem> contents;
9888 input Boolean addFunctions;
9889 input Boolean isPublic;
9890 output list<String> res;
9891 algorithm
9892 res := matchcontinue (contents,addFunctions,isPublic)
9893 local
9894 list<Absyn.ElementItem> rest;
9895 String ident, typeStr, dirStr, str;
9896 Absyn.Class class_;
9897 Absyn.Path path;
9898 list<Absyn.ComponentItem> components;
9899 Absyn.Direction direction;
9900 Absyn.TypeSpec ts;
9901 Absyn.Variability variability;
9902 Absyn.ElementAttributes attr;
9903 list<String> res2;
9904
9905 case ({},_,_) then {};
9906 case (Absyn.ELEMENTITEM(Absyn.ELEMENT(specification = Absyn.CLASSDEF(replaceable_ = false, class_ = class_)))::rest,_,_)
9907 algorithm
9908 ✗ res := getDefinitionContent(rest,addFunctions,isPublic);
9909 ✗ str := getDefinitionsClass(class_,addFunctions);
9910 then str::res;
9911 case (Absyn.ELEMENTITEM(Absyn.ELEMENT(specification = Absyn.CLASSDEF(replaceable_ = true, class_ = class_)))::rest,_,_)
9912 algorithm
9913 ✗ res := getDefinitionContent(rest,addFunctions,isPublic);
9914 ✗ ident := getDefinitionsReplaceableClass(class_);
9915 then ident :: res;
9916 case (Absyn.ELEMENTITEM(Absyn.ELEMENT(specification = Absyn.COMPONENTS(typeSpec = ts,components = components, attributes = (attr as Absyn.ATTR(direction = direction, variability = variability)))))::rest,_,true)
9917 algorithm
9918 ✗ typeStr := getDefinitionTypeSpecPathString(ts);
9919 ✗ dirStr := getDefinitionDirString(direction, variability, addFunctions);
9920 ✗ res := getDefinitionComponents(typeStr, dirStr, getDefinitionDimensions(ts,attr), components);
9921 ✗ res2 := getDefinitionContent(rest,addFunctions,isPublic);
9922 ✗ then listAppend(res,res2);
9923 case (Absyn.ELEMENTITEM(Absyn.ELEMENT(specification = Absyn.EXTENDS(path = path)))::rest,false,true)
9924 algorithm
9925 ✗ typeStr := "(extends " + getDefinitionPathString(path) + ")";
9926 ✗ res := getDefinitionContent(rest,addFunctions,isPublic);
9927 then typeStr :: res;
9928 case (_::rest,_,_)
9929 ✗ then getDefinitionContent(rest,addFunctions,isPublic);
9930 end matchcontinue;
9931 end getDefinitionContent;
9932
9933 protected function getDefinitionDirString
9934 input Absyn.Direction dir;
9935 input Absyn.Variability variability;
9936 input Boolean isFunction;
9937 output String res;
9938 algorithm
9939 res := match (dir, isFunction)
9940 case (Absyn.INPUT(),true) then "input ";
9941 case (Absyn.OUTPUT(),true) then "output ";
9942 case (_, false)
9943 algorithm
9944 ✗ failure(Absyn.CONST() := variability);
9945 then "";
9946 end match;
9947 end getDefinitionDirString;
9948
9949 protected function getDefinitionComponents
9950 input String typeStr;
9951 input String dirStr;
9952 input Integer numDim;
9953 input list<Absyn.ComponentItem> components;
9954 output list<String> res;
9955 algorithm
9956 res := match components
9957 local
9958 list<Absyn.ComponentItem> rest;
9959 String ident;
9960 list<Absyn.Subscript> l;
9961 Integer sumDim;
9962
9963 case {} then {};
9964 case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = ident, arrayDim = l))::rest algorithm
9965 ✗ sumDim := numDim + listLength(l);
9966 ✗ ident := dirStr + (if numDim == 0 then "" else ("[" + intString(sumDim))) + typeStr + " " + ident;
9967 ✗ ident := "(" + ident + ")";
9968 ✗ res := getDefinitionComponents(typeStr,dirStr,numDim,rest);
9969 then ident :: res;
9970 ✗ case rest then getDefinitionComponents(typeStr,dirStr,numDim,rest);
9971 end match;
9972 end getDefinitionComponents;
9973
9974 protected function getDefinitionTypeVars
9975 input list<String> inTypeVars;
9976 input list<String> inDefinitions;
9977 output list<String> outDefinitions = inDefinitions;
9978 algorithm
9979 ✗ for ty_var in listReverse(inTypeVars) loop
9980 ✗ outDefinitions := ("(replaceable type " + ty_var + ")") :: outDefinitions;
9981 end for;
9982 end getDefinitionTypeVars;
9983
9984 /* End getDefinitions */
9985
9986 public function parseFile
9987 "@author adrpo
9988 This function just parses a file and report contents ONLY if the
9989 file is newer than the one already loaded."
9990 input String fileName "Filename to load";
9991 input String encoding;
9992 input Boolean updateProgram=false;
9993 output list<Absyn.Path> topClassNamesQualified "The names of the classes from file, qualified!";
9994 protected
9995 Absyn.Program parsed;
9996 String dir,filename;
9997 Boolean lveStarted = false;
9998 Option<Integer> lveInstance = NONE();
9999 algorithm
10000
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if not System.regularFileExists(fileName) then
10001 topClassNamesQualified := {};
10002 ✗ return;
10003 end if;
10004 4 (dir,filename) := Util.getAbsoluteDirectoryAndFile(fileName);
10005
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
4 if filename == "package.moc" then
10006 ✗ (lveStarted, lveInstance) := Parser.startLibraryVendorExecutable(dir);
10007 ✗ if not lveStarted then
10008 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"Unable to start library vendor executable."});
10009 topClassNamesQualified := {};
10010 ✗ return;
10011 end if;
10012 end if;
10013 4 parsed := Parser.parse(fileName,encoding,dir,lveInstance);
10014 4 parsed := MetaUtil.createMetaClassesInProgram(parsed);
10015 4 topClassNamesQualified := getTopQualifiedClassnames(parsed);
10016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (lveStarted) then
10017 ✗ Parser.stopLibraryVendorExecutable(lveInstance);
10018 end if;
10019
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if updateProgram then
10020 2 SymbolTable.setAbsyn(ProgramUtil.updateProgram(parsed, SymbolTable.getAbsyn()));
10021 end if;
10022 end parseFile;
10023
10024 public function getSCodeClassNamesRecursive
10025 "Returns a string with all the classes for a given path."
10026 input SCode.Program inProgram;
10027 output list<Absyn.Path> paths;
10028 algorithm
10029 ✗ paths := List.fold1(inProgram,getSCodeClassNamesRecursiveWork,NONE(),{});
10030 end getSCodeClassNamesRecursive;
10031
10032 protected function getSCodeClassNamesRecursiveWork
10033 "Returns a string with all the classes for a given path."
10034 input SCode.Element inElement;
10035 input Option<Absyn.Path> inPath;
10036 input list<Absyn.Path> inAcc;
10037 output list<Absyn.Path> paths;
10038 algorithm
10039 paths := match (inElement,inPath,inAcc)
10040 local
10041 list<SCode.Element> classes;
10042 list<Absyn.Path> acc;
10043 Absyn.Path path;
10044 String name;
10045 case (SCode.CLASS(name=name),NONE(),acc)
10046 algorithm
10047 ✗ path := Absyn.IDENT(name);
10048 acc := path::acc;
10049 ✗ classes := SCodeUtil.getClassElements(inElement);
10050 ✗ acc := List.fold1(classes,getSCodeClassNamesRecursiveWork,SOME(path),acc);
10051 then acc;
10052 case (SCode.CLASS(name=name),SOME(path),acc)
10053 algorithm
10054 ✗ path := AbsynUtil.suffixPath(path,name);
10055 acc := path::acc;
10056 ✗ classes := SCodeUtil.getClassElements(inElement);
10057 ✗ acc := List.fold1(classes,getSCodeClassNamesRecursiveWork,SOME(path),acc);
10058 then acc;
10059 else inAcc;
10060 end match;
10061 end getSCodeClassNamesRecursiveWork;
10062
10063 public function getAllInheritedClasses
10064 input Absyn.Path inClassName;
10065 input Absyn.Program inProgram;
10066 output list<Absyn.Path> outBaseClassNames;
10067 algorithm
10068 outBaseClassNames :=
10069 matchcontinue (inClassName,inProgram)
10070 local
10071 Absyn.Path p_class;
10072 list<Absyn.Path> paths;
10073 Absyn.Class cdef;
10074 list<Absyn.ElementSpec> exts;
10075 Absyn.Program p;
10076
10077 case (p_class,p)
10078 algorithm
10079 ✗ cdef := ProgramUtil.getPathedClassInProgram(p_class, p);
10080 ✗ exts := InteractiveUtil.getExtendsElementspecInClass(cdef);
10081 ✗ paths := List.map(exts, InteractiveUtil.getBaseClassNameFromExtends);
10082 then
10083 paths;
10084 else {};
10085 end matchcontinue;
10086 end getAllInheritedClasses;
10087
10088 public function printIstmtStr "Prints an interactive statement to a string."
10089 input GlobalScript.Statements inStatements;
10090 output String strIstmt;
10091 algorithm
10092 383 strIstmt := GlobalScriptDump.printIstmtsStr(inStatements);
10093 end printIstmtStr;
10094
10095 protected function getClassEnvNoElaboration " Retrieves the environment of the class, including the frame of the class
10096 itself by partially instantiating it.
10097
10098 If partial instantiation fails, a full instantiation is performed.
10099
10100 This can happen e.g. for
10101 model A
10102 model Resistor
10103 Pin p,n;
10104 constant Integer n_conn = cardinality(p);
10105 equation connect(p,n);
10106 end A;
10107
10108 where partial instantiation fails since cardinality(p) can not be determined."
10109 input Absyn.Program inProgram;
10110 input Absyn.Path inClassPath;
10111 input FCore.Graph inEnv;
10112 output FCore.Graph outEnv;
10113 protected
10114 SCode.Element cl;
10115 String id;
10116 SCode.Encapsulated encflag;
10117 SCode.Restriction restr;
10118 FCore.Graph env;
10119 ClassInf.State ci_state;
10120 FCore.Cache cache;
10121 algorithm
10122 ✗ (cache, (cl as SCode.CLASS(name = id, encapsulatedPrefix = encflag, restriction = restr)), env) :=
10123 Lookup.lookupClass(FCore.emptyCache(), inEnv, inClassPath);
10124 ✗ env := FGraph.openScope(env, encflag, id, FGraph.restrictionToScopeType(restr));
10125 ✗ ci_state := ClassInfUtil.start(restr, FGraph.getGraphName(env));
10126
10127 // First try partial instantiation
10128 try
10129 ✗ (_, outEnv) := Inst.partialInstClassIn(cache, env, InnerOuter.emptyInstHierarchy,
10130 DAE.NOMOD(), DAE.NOPRE(), ci_state, cl, SCode.PUBLIC(), {}, 0);
10131 else
10132 ✗ (_, outEnv) := Inst.instClassIn(cache, env, InnerOuter.emptyInstHierarchy,
10133 UnitAbsyn.noStore, DAE.NOMOD(), DAE.NOPRE(), ci_state, cl,
10134 SCode.PUBLIC(), {}, false, InstTypes.INNER_CALL(), ConnectionGraph.EMPTY,
10135 Connect.emptySet, NONE());
10136 end try;
10137 end getClassEnvNoElaboration;
10138
10139 public function setComponentDimensions
10140 "Sets a component dimensions."
10141 input Absyn.Path inClass;
10142 input Absyn.Path inComponentName;
10143 input list<Absyn.Exp> inDimensions;
10144 input Absyn.Program inProgram;
10145 output Absyn.Program outProgram;
10146 output Boolean outResult;
10147 protected
10148 Absyn.Within within_;
10149 Absyn.Class cls;
10150 algorithm
10151 try
10152 ✗ within_ := ProgramUtil.buildWithin(inClass);
10153 ✗ cls := ProgramUtil.getPathedClassInProgram(inClass, inProgram);
10154 ✗ cls := setComponentDimensionsInClass(cls, inComponentName, inDimensions);
10155 ✗ outProgram := ProgramUtil.updateProgram(Absyn.PROGRAM({cls}, within_), inProgram);
10156 outResult := true;
10157 else
10158 outProgram := inProgram;
10159 outResult := false;
10160 end try;
10161 end setComponentDimensions;
10162
10163 protected function setComponentDimensionsInClass
10164 " Sets the dimensions on a component in a class."
10165 input Absyn.Class inClass;
10166 input Absyn.Path inComponentName;
10167 input list<Absyn.Exp> inDimensions;
10168 output Absyn.Class outClass = inClass;
10169 algorithm
10170 ✗ (outClass, true) := AbsynUtil.traverseClassComponents(inClass,
10171 function setComponentDimensionsInCompitems(inComponentName = inComponentName, inDimensions = inDimensions), false);
10172 end setComponentDimensionsInClass;
10173
10174 protected function setComponentDimensionsInCompitems
10175 "Helper function to setComponentDimensions.
10176 Sets the dimensions in a ComponentItem."
10177 input list<Absyn.ComponentItem> inComponents;
10178 input Boolean inFound;
10179 input Absyn.Path inComponentName;
10180 input list<Absyn.Exp> inDimensions;
10181 output list<Absyn.ComponentItem> outComponents = {};
10182 output Boolean outFound;
10183 output Boolean outContinue;
10184 protected
10185 Absyn.ComponentItem item;
10186 list<Absyn.ComponentItem> rest_items = inComponents;
10187 Absyn.Component comp;
10188 String comp_id;
10189 algorithm
10190 ✗ comp_id := AbsynUtil.pathFirstIdent(inComponentName);
10191
10192 // Try to find the component we're looking for.
10193 ✗ while not listEmpty(rest_items) loop
10194 ✗ item :: rest_items := rest_items;
10195
10196 ✗ if AbsynUtil.componentName(item) == comp_id then
10197 // Found component, propagate the modifier to it.
10198 () := match item
10199 case Absyn.COMPONENTITEM(component = comp as Absyn.COMPONENT())
10200 algorithm
10201 ✗ comp.arrayDim := List.map(inDimensions, AbsynUtil.makeSubscript);
10202 ✗ item.component := comp;
10203 then
10204 ();
10205 end match;
10206
10207 // Reassemble the item list and return.
10208 ✗ outComponents := List.append_reverse(outComponents, item :: rest_items);
10209 outFound := true;
10210 outContinue := false;
10211 ✗ return;
10212 end if;
10213 outComponents := item :: outComponents;
10214 end while;
10215
10216 // Component not found, continue looking.
10217 outComponents := inComponents;
10218 outFound := false;
10219 outContinue := true;
10220 end setComponentDimensionsInCompitems;
10221
10222 public function getInstantiatedParametersAndValues
10223 input Option<DAE.DAElist> odae;
10224 output list<String> parametersAndValues = {};
10225 protected
10226 list<DAE.Element> els, params;
10227 list<String> strs = {};
10228 String s;
10229 algorithm
10230 parametersAndValues := match odae
10231 case SOME(DAE.DAE(els))
10232 algorithm
10233 ✗ params := DAEUtil.getParameters(els, {});
10234
10235 ✗ for p in params loop
10236 strs := match p
10237 case DAE.VAR(componentRef = DAE.CREF_IDENT(s))
10238 ✗ then (s + DAEDump.dumpVarBindingStr(p.binding)) :: strs;
10239
10240 else strs;
10241 end match;
10242 end for;
10243 ✗ then
10244 Dangerous.listReverseInPlace(strs);
10245
10246 else strs;
10247 end match;
10248 end getInstantiatedParametersAndValues;
10249
10250 public function getAccessAnnotation
10251 "Returns the Protection(access=) annotation of a class.
10252 This is annotated with the annotation:
10253 annotation(Protection(access = Access.documentation)); in the class definition"
10254 input Absyn.Path className;
10255 input Absyn.Program p;
10256 output String access;
10257 algorithm
10258 access := match p
10259 local
10260 String accessStr;
10261 case _
10262 algorithm
10263 6 accessStr := ProgramUtil.getNamedAnnotationExp(className, p, Absyn.IDENT("Protection"), SOME(""), getAccessAnnotationString);
10264 then
10265 accessStr;
10266 else "";
10267 end match;
10268 end getAccessAnnotation;
10269
10270 protected function getAccessAnnotationString
10271 "Extractor function for getAccessAnnotation"
10272 input Option<Absyn.Modification> mod;
10273 output String access;
10274 algorithm
10275 access := match mod
10276 local
10277 list<Absyn.ElementArg> arglst;
10278
10279 case SOME(Absyn.CLASSMOD(elementArgLst = arglst))
10280 ✗ then getAccessAnnotationString2(arglst);
10281
10282 end match;
10283 end getAccessAnnotationString;
10284
10285 protected function getAccessAnnotationString2
10286 "Extractor function for getAccessAnnotation"
10287 input list<Absyn.ElementArg> eltArgs;
10288 output String access;
10289 algorithm
10290 access := match eltArgs
10291 local
10292 list<Absyn.ElementArg> xs;
10293 Absyn.ComponentRef cref;
10294 String name;
10295
10296 case {} then "";
10297
10298 case Absyn.MODIFICATION(path = Absyn.IDENT(name="access"),
10299 modification = SOME(Absyn.CLASSMOD(eqMod=Absyn.EQMOD(exp=Absyn.CREF(cref)))))::_
10300 algorithm
10301 ✗ name := Dump.printComponentRefStr(cref);
10302 then name;
10303
10304 case _::xs
10305 algorithm
10306 ✗ name := getAccessAnnotationString2(xs);
10307 then name;
10308
10309 end match;
10310 end getAccessAnnotationString2;
10311
10312 public function checkAccessAnnotationAndEncryption
10313 input Absyn.Path path;
10314 input Absyn.Program p;
10315 output Access access;
10316 protected
10317 String fileName;
10318 Boolean encryptedClass;
10319 algorithm
10320 try
10321 77 Absyn.CLASS(info=SOURCEINFO(fileName=fileName)) := ProgramUtil.getPathedClassInProgram(path, p);
10322 77 encryptedClass := StringUtil.endsWith(fileName, ".moc");
10323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if encryptedClass then
10324 access := match getAccessAnnotation(path, p)
10325 case "Access.hide" then Access.hide;
10326 case "Access.icon" then Access.icon;
10327 case "Access.documentation" then Access.documentation;
10328 case "Access.diagram" then Access.diagram;
10329 case "Access.nonPackageText" then Access.nonPackageText;
10330 case "Access.nonPackageDuplicate" then Access.nonPackageDuplicate;
10331 case "Access.packageText" then Access.packageText;
10332 case "Access.packageDuplicate" then Access.packageDuplicate;
10333 // If the class doesn't have the access annotation then look for it in the parent class.
10334 case _ guard not AbsynUtil.pathIsIdent(path)
10335 ✗ then checkAccessAnnotationAndEncryption(AbsynUtil.stripLast(path), p);
10336 // if a class is encrypted and no Protection annotation is defined, the
10337 // access annotation has the default value Access.documentation
10338 else Access.documentation;
10339 end match;
10340 else
10341 access := Access.all;
10342 end if;
10343 else
10344 access := Access.all;
10345 end try;
10346 end checkAccessAnnotationAndEncryption;
10347
10348 public function astContainsEncryptedClass
10349 input Absyn.Program inProgram;
10350 output Boolean containsEncryptedClass = false;
10351 protected
10352 list<Absyn.Class> classes;
10353 String fileName;
10354 algorithm
10355 1923 Absyn.PROGRAM(classes=classes) := inProgram;
10356
2/2
✓ Branch 0 taken 4570 times.
✓ Branch 1 taken 1923 times.
6493 for c in classes loop
10357 4570 Absyn.CLASS(info=SOURCEINFO(fileName=fileName)) := c;
10358
1/2
✓ Branch 1 taken 4570 times.
✗ Branch 2 not taken.
4570 containsEncryptedClass := containsEncryptedClass or StringUtil.endsWith(fileName, ".moc");
10359 if containsEncryptedClass then break; end if;
10360 end for;
10361 end astContainsEncryptedClass;
10362
10363 public function addEquation
10364 input Absyn.Path clsPath;
10365 input String eqStr;
10366 input Boolean isInitial;
10367 output Boolean success = false;
10368 protected
10369 Absyn.Program program;
10370 Absyn.EquationItem eq;
10371 algorithm
10372 try
10373 4 eq := Parser.stringEq(eqStr);
10374
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
6 program := transformPathedClassInProgram(clsPath, SymbolTable.getAbsyn(),
10375 function AbsynUtil.appendEquation(eq = eq, isInitial = isInitial));
10376 4 SymbolTable.setAbsyn(program);
10377 success := true;
10378 else
10379 end try;
10380 end addEquation;
10381
10382 public function updateEquation
10383 input Absyn.Path clsPath;
10384 input String oldEq;
10385 input String newEq;
10386 input Boolean matchAll;
10387 input Boolean matchShallow;
10388 input Boolean matchDescription;
10389 input Boolean mergeDescription;
10390 output Boolean success;
10391 protected
10392 Absyn.Program program;
10393 Absyn.EquationItem old_eq;
10394 Option<Absyn.EquationItem> new_eq;
10395 algorithm
10396 try
10397 10 old_eq := Parser.stringEq(oldEq);
10398
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
10 new_eq := if stringEmpty(newEq) then NONE() else SOME(Parser.stringEq(newEq));
10399
8/8
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 9 times.
✓ Branch 7 taken 1 time.
38 program := transformPathedClassInProgram(clsPath, SymbolTable.getAbsyn(),
10400 function updateEquation_impl(oldEq = old_eq, newEq = new_eq, matchAll = matchAll,
10401 matchShallow = matchShallow, matchDescription = matchDescription, mergeDescription = mergeDescription));
10402 8 SymbolTable.setAbsyn(program);
10403 success := true;
10404 else
10405 success := false;
10406 end try;
10407 end updateEquation;
10408
10409 protected function updateEquation_impl
10410 input output Absyn.Class cls;
10411 input Absyn.EquationItem oldEq;
10412 input Option<Absyn.EquationItem> newEq;
10413 input Boolean matchAll;
10414 input Boolean matchShallow;
10415 input Boolean matchDescription;
10416 input Boolean mergeDescription;
10417 protected
10418 Absyn.ClassPart part;
10419 list<Absyn.ClassPart> rest_parts, accum_parts = {};
10420 Absyn.EquationItem eq, new_eq;
10421 list<Absyn.EquationItem> rest_eqs, accum_eqs;
10422 Boolean found = false, found_in_part;
10423
10424 function merge_desc
10425 input Absyn.EquationItem oldEq;
10426 input output Absyn.EquationItem newEq;
10427 protected
10428 Absyn.Comment cmt;
10429 algorithm
10430 () := match (oldEq, newEq)
10431 case (Absyn.EquationItem.EQUATIONITEM(), Absyn.EquationItem.EQUATIONITEM())
10432 algorithm
10433
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 if isSome(oldEq.comment) then
10434
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 if isNone(newEq.comment) then
10435 1 newEq.comment := oldEq.comment;
10436 else
10437 ✗ SOME(cmt) := newEq.comment;
10438 ✗ if isNone(cmt.annotation_) then
10439 ✗ cmt.annotation_ := AbsynUtil.getCommentOptAnnotation(oldEq.comment);
10440 else
10441 ✗ cmt.comment := AbsynUtil.getCommentOptComment(oldEq.comment);
10442 end if;
10443 ✗ newEq.comment := SOME(cmt);
10444 end if;
10445 end if;
10446 then
10447 ();
10448
10449 else ();
10450 end match;
10451 end merge_desc;
10452 algorithm
10453 10 rest_parts := AbsynUtil.getClassPartsInClass(cls);
10454
10455
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 3 times.
30 while not listEmpty(rest_parts) loop
10456 27 part :: rest_parts := rest_parts;
10457 27 rest_eqs := AbsynUtil.getEquationItemsInPart(part);
10458 accum_eqs := {};
10459 found_in_part := false;
10460
10461
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 20 times.
46 while not listEmpty(rest_eqs) loop
10462 26 eq :: rest_eqs := rest_eqs;
10463
10464
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 16 times.
26 if AbsynUtil.equationItemEqual(eq, oldEq, shallow = matchShallow, ignoreComment = not matchDescription) then
10465
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7 times.
10 if isSome(newEq) then
10466 3 new_eq := Util.getOption(newEq);
10467
10468
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
3 if mergeDescription then
10469 1 new_eq := merge_desc(eq, new_eq);
10470 end if;
10471
10472 accum_eqs := new_eq :: accum_eqs;
10473 end if;
10474
10475 found_in_part := true;
10476 found := true;
10477
10478
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
10 if not matchAll then
10479 7 accum_eqs := List.append_reverse(rest_eqs, accum_eqs);
10480 7 break;
10481 end if;
10482 else
10483 accum_eqs := eq :: accum_eqs;
10484 end if;
10485 end while;
10486
10487
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 19 times.
27 if found_in_part then
10488 8 part := AbsynUtil.setEquationItemsInPart(Dangerous.listReverseInPlace(accum_eqs), part);
10489 accum_parts := part :: accum_parts;
10490
10491
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 7 times.
8 if not matchAll then
10492 7 accum_parts := List.append_reverse(rest_parts, accum_parts);
10493 7 break;
10494 end if;
10495 else
10496 accum_parts := part :: accum_parts;
10497 end if;
10498 end while;
10499
10500
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if not found then
10501 2 fail();
10502 end if;
10503
10504 8 cls := AbsynUtil.setClassPartsInClass(Dangerous.listReverseInPlace(accum_parts), cls);
10505 end updateEquation_impl;
10506
10507 annotation(__OpenModelica_Interface="backend_main");
10508 end Interactive;
10509