Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 76.5% 448 / 0 / 586
Functions: 50.0% 2 / 1 / 5
Branches: 70.9% 241 / 0 / 340

OMCompiler/Compiler/NFFrontEnd/NFInstanceAPI.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 NFInstanceAPI
37 "The model-instance API: instantiate a class and dump what it looks like as
38 JSON (issue #15219). Split out of NFApi so that a tool needing only this —
39 the documentation generator, which renders icons and member tables from a
40 model instance — does not link the backend. NFApi keeps the scripting
41 entry points and passes SymbolTable's program in."
42
43 import Absyn;
44 import AbsynUtil;
45 import SCode;
46 import DAE;
47 import NFModifier.Modifier;
48 import JSON;
49
50 protected
51
52 import NFInst;
53 import Inst = NFInst;
54 import NFCall.Call;
55 import NFInstContext;
56 import NFModifier;
57 import NFBinding.Binding;
58 import NFComponent.Component;
59 import ComponentRef = NFComponentRef;
60 import Dimension = NFDimension;
61 import Expression = NFExpression;
62 import Import = NFImport;
63 import NFClass.Class;
64 import NFInstNode;
65 import MutableWeak;
66 import NFInstNode.InstNode;
67 import NFInstNode.InstNodeType;
68 import Equation = NFEquation;
69 import NFType.Type;
70 import Subscript = NFSubscript;
71 import InstContext = NFInstContext;
72
73 import Absyn.Path;
74 import AbsynToSCode;
75 import Config;
76 import Dump;
77 import Error;
78 import ErrorExt;
79 import Mutable;
80 import ExecStat.execStat;
81 import FBuiltin;
82 import Flags;
83 import Global;
84 import List;
85 import Lookup = NFLookup;
86 import MetaModelica.Dangerous;
87 import MetaModelica.Dangerous.listReverseInPlace;
88 import Ceval = NFCeval;
89 import NFClassTree.ClassTree;
90 import NFPrefixes.{Variability, Purity};
91 import NFSections.Sections;
92 import Parser;
93 import Restriction = NFRestriction;
94 import SimplifyExp = NFSimplifyExp;
95 import Settings;
96 import Typing = NFTyping;
97 import UnorderedMap;
98 import Util;
99 import SCodeUtil;
100 import SCodeDump;
101 import ElementSource;
102 import InstSettings = NFInst.InstSettings;
103
104 constant InstContext.Type ANNOTATION_CONTEXT = intBitOr(NFInstContext.RELAXED, NFInstContext.ANNOTATION);
105 constant InstContext.Type INST_API_ANNOTATION_CONTEXT = intBitOr(ANNOTATION_CONTEXT, NFInstContext.INSTANCE_API);
106
107 public
108
109 function annotationProgram
110 "The graphical annotation definitions, parsed from lib/omc. A copy of
111 InteractiveUtil.modelicaAnnotationProgram, which lives in the backend."
112 input String annotationVersion "1.x or 2.x or 3.x";
113 output Absyn.Program program;
114 protected
115 String filename;
116 algorithm
117 2057 filename := Settings.getInstallationDirectoryPath() +
118 "/lib/omc/AnnotationsBuiltin_" +
119 Util.stringReplaceChar(annotationVersion, ".", "_") +
120 ".mo";
121 2057 program := Parser.parse(filename, "UTF-8");
122 end annotationProgram;
123
124 public function mkTop
125 "The `top` scope the instance API instantiates in. `scodeProgram` is the
126 already translated form of `absynProgram` when the caller has one — the
127 scripting API passes SymbolTable's, which saves retranslating the whole
128 library on every call."
129 input Absyn.Program absynProgram;
130 input Option<SCode.Program> scodeProgram = NONE();
131 input String name;
132 output SCode.Program program;
133 output InstNode top;
134 protected
135 SCode.Program scode_builtin, graphicProgramSCode;
136 Absyn.Program placementProgram;
137 list<tuple<Absyn.Program, tuple<SCode.Program, InstNode>>> cache;
138 Boolean reuse;
139 algorithm
140 4569 cache := getGlobalRoot(Global.instNFNodeCacheIndex);
141 // if absyn is the same, all fine, reuse
142
4/4
✓ Branch 0 taken 2562 times.
✓ Branch 1 taken 2007 times.
✓ Branch 4 taken 2512 times.
✓ Branch 5 taken 50 times.
4569 reuse := if listEmpty(cache) then false else referenceEq(absynProgram, Util.tuple21(listHead(cache)));
143 if reuse then
144 2512 (program, top) := Util.tuple22(listHead(cache));
145 2512 InstNode.clearGeneratedInners(top);
146 // Nodes made from here on belong to the cached tree, so they have to be
147 // rooted there rather than in whatever run was last to build a top node.
148 2512 MutableWeak.useRoots(InstNode.scopeRoots(top));
149 else
150
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 2007 times.
2057 if not listEmpty(cache) then
151 50 setGlobalRoot(Global.instNFNodeCacheIndex, {});
152 end if;
153 2057 (_, scode_builtin) := FBuiltin.getInitialFunctions();
154
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2057 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2057 times.
2057 if isSome(scodeProgram) then
155 2057 SOME(program) := scodeProgram;
156 else
157 ✗ program := AbsynToSCode.translateAbsyn2SCode(absynProgram);
158 end if;
159 2057 program := listAppend(scode_builtin, program);
160 2057 placementProgram := annotationProgram(Config.getAnnotationVersion());
161 2057 graphicProgramSCode := AbsynToSCode.translateAbsyn2SCode(placementProgram);
162
163 2057 Inst.resetGlobalFlags();
164
165 // Create a root node from the given top-level classes.
166 2057 top := NFInst.makeTopNode(program, graphicProgramSCode);
167
168
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2057 times.
2057 if Flags.isSet(Flags.EXEC_STAT) then
169 ✗ execStat("NFInstanceAPI.mkTop("+ name +")");
170 end if;
171
172 4114 setGlobalRoot(Global.instNFNodeCacheIndex, {(absynProgram, (program, top))});
173 end if;
174 end mkTop;
175
176 protected
177
178 uniontype InstanceTree
179 record COMPONENT
180 InstNode node;
181 Option<Binding> binding;
182 InstanceTree cls;
183 end COMPONENT;
184
185 record CLASS
186 InstNode node;
187 list<InstanceTree> elements;
188 Boolean isExtends;
189 end CLASS;
190
191 record BUILTIN_BASE_CLASS
192 String name;
193 end BUILTIN_BASE_CLASS;
194
195 record EMPTY
196 end EMPTY;
197 end InstanceTree;
198
199 constant InstanceTree ENUM_BASE = InstanceTree.BUILTIN_BASE_CLASS("enumeration");
200
201
202 public function buildModelInstanceJSON
203 "Instantiates the given model and builds the JSON structure describing the
204 model instance. Shared by getModelInstance and getModelInstanceReference."
205 input Absyn.Program absynProgram;
206 input Option<SCode.Program> scodeProgram;
207 input Absyn.Path classPath;
208 input Absyn.Path contextPath;
209 input String modifier;
210 output JSON json;
211 protected
212 InstNode top, cls_node;
213 InstContext.Type context;
214 InstanceTree inst_tree;
215 InstSettings inst_settings;
216 Modifier mod;
217 algorithm
218 48 context := InstContext.set(NFInstContext.RELAXED, NFInstContext.CLASS);
219 48 context := InstContext.set(context, NFInstContext.INSTANCE_API);
220 inst_settings := InstSettings.SETTINGS(mergeExtendsSections = false, resizableArrays = false);
221
222 48 (_, top) := mkTop(absynProgram, scodeProgram, AbsynUtil.pathString(classPath));
223 48 mod := parseModifier(modifier, top);
224 48 cls_node := Inst.lookupRootClass(classPath, top, context);
225
226
2/2
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 47 times.
48 if SCodeUtil.isFunction(InstNode.definition(cls_node)) then
227 1 context := InstContext.unset(context, NFInstContext.CLASS);
228 1 context := InstContext.set(context, NFInstContext.FUNCTION);
229 end if;
230
231
3/4
✓ Branch 1 taken 47 times.
✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 47 times.
48 if AbsynUtil.pathFirstIdent(contextPath) <> "__NoContext" then
232 1 cls_node := InstNode.setNodeType(InstNodeType.ROOT_CLASS(NFInstNode.NO_SCOPE, SOME(contextPath)), cls_node);
233 end if;
234
235 48 cls_node := Inst.instantiateRootClass(cls_node, context, mod);
236 48 execStat("Inst.instantiateRootClass");
237 48 inst_tree := buildInstanceTree(cls_node);
238 48 execStat("NFInstanceAPI.buildInstanceTree");
239 48 Inst.instExpressions(cls_node, context = context, settings = inst_settings);
240 48 Inst.updateImplicitVariability(cls_node, Flags.isSet(Flags.EVAL_PARAM), context);
241 48 execStat("Inst.instExpressions");
242
243 48 Typing.typeClassType(cls_node, NFBinding.EMPTY_BINDING, context, cls_node);
244 48 Typing.typeComponents(cls_node, context);
245 48 execStat("Typing.typeComponents");
246 48 Typing.typeBindings(cls_node, context);
247 48 execStat("Typing.typeBinding");
248
249 48 json := dumpJSONInstanceTree(inst_tree, cls_node);
250 48 execStat("NFInstanceAPI.dumpJSONInstanceTree");
251 end buildModelInstanceJSON;
252
253 public function buildModelInstanceAnnotationJSON
254 "Instantiates the given model and builds the JSON structure describing its
255 annotation. Shared by getModelInstanceAnnotation and
256 getModelInstanceAnnotationReference."
257 input Absyn.Program absynProgram;
258 input Option<SCode.Program> scodeProgram;
259 input Absyn.Path classPath;
260 input list<String> filter;
261 output JSON json;
262 protected
263 InstNode top, cls_node;
264 InstContext.Type context;
265 algorithm
266 3 context := InstContext.set(NFInstContext.RELAXED, NFInstContext.CLASS);
267 3 context := InstContext.set(context, NFInstContext.INSTANCE_API);
268
269 3 (_, top) := mkTop(absynProgram, scodeProgram, AbsynUtil.pathString(classPath));
270 3 cls_node := Inst.lookupRootClass(classPath, top, context);
271 3 cls_node := InstNode.resolveInner(cls_node);
272
273 3 json := dumpJSONInstanceAnnotation(cls_node, filter);
274 end buildModelInstanceAnnotationJSON;
275
276 public function buildModelInstanceIconJSON
277 input Absyn.Program absynProgram;
278 input Option<SCode.Program> scodeProgram;
279 input Absyn.Path classPath;
280 output JSON json;
281 protected
282 InstNode top;
283 algorithm
284 15 (_, top) := mkTop(absynProgram, scodeProgram, AbsynUtil.pathString(classPath));
285 15 json := iconJSONFromTop(top, classPath);
286 end buildModelInstanceIconJSON;
287
288 public function diagramJSONFromTop
289 "What a diagram is drawn from: the class' own Diagram layer with its extends
290 chain, every component it shows — inherited ones included — with its
291 Placement and its type's Icon, and the connect equations with their Line
292 annotations. Nothing is typed, only looked up and expanded, so this costs
293 about what the icon dump costs."
294 input InstNode top;
295 input Absyn.Path classPath;
296 output JSON json;
297 protected
298 InstNode cls_node;
299 InstContext.Type context;
300 JSON components = JSON.emptyArray(), connections = JSON.emptyArray();
301 algorithm
302 ✗ context := InstContext.set(NFInstContext.RELAXED, NFInstContext.CLASS);
303 ✗ context := InstContext.set(context, NFInstContext.INSTANCE_API);
304
305 ✗ cls_node := Inst.lookupRootClass(classPath, top, context);
306 ✗ cls_node := InstNode.resolveInner(cls_node);
307
308 ✗ json := dumpJSONInstanceAnnotation(cls_node, {"Diagram"}, dumpDerivedBase = true);
309 ✗ (components, connections) := dumpJSONDiagramParts(cls_node, context, components, connections, 0);
310 ✗ json := JSON.addPair("components", components, json);
311 ✗ json := JSON.addPair("connections", connections, json);
312 end diagramJSONFromTop;
313
314 function dumpJSONDiagramParts
315 "A class' components and connections, base classes' first so a derived
316 component is drawn over an inherited one."
317 input InstNode node;
318 input InstContext.Type context;
319 input output JSON components;
320 input output JSON connections;
321 input Integer depth;
322 protected
323 InstNode ty_node;
324 JSON e;
325 SCode.Element def;
326 list<SCode.Equation> eqs;
327 algorithm
328 ✗ if depth > 16 then
329 ✗ return;
330 end if;
331
332 ✗ for ext in ClassTree.getExtends(Class.classTree(InstNode.getClass(node))) loop
333 ✗ (components, connections) :=
334 dumpJSONDiagramParts(ext, context, components, connections, depth + 1);
335 end for;
336
337 ✗ def := InstNode.definition(node);
338
339 ✗ for el in SCodeUtil.getClassElements(def) loop
340 () := match el
341 case SCode.Element.COMPONENT()
342 algorithm
343 try
344 ✗ ty_node := Lookup.lookupClassName(AbsynUtil.typeSpecPath(el.typeSpec), node, context, el.info);
345 ✗ ty_node := Inst.expand(ty_node, context);
346 ✗ e := JSON.addPair("$kind", JSON.STRING("component"), JSON.makeNull());
347 ✗ e := JSON.addPair("name", JSON.makeString(el.name), e);
348 ✗ e := dumpJSONAnnotationOpt(el.comment.annotation_, node, {"Placement"}, false, e);
349 ✗ e := JSON.addPair("type", diagramComponentIcon(ty_node), e);
350 ✗ components := JSON.addElement(e, components);
351 else
352 end try;
353 then ();
354
355 else ();
356 end match;
357 end for;
358
359 eqs := match def
360 case SCode.Element.CLASS(classDef = SCode.ClassDef.PARTS(normalEquationLst = eqs)) then eqs;
361 else {};
362 end match;
363
364 ✗ for eq in eqs loop
365 () := match eq
366 case SCode.Equation.EQ_CONNECT()
367 algorithm
368 ✗ e := dumpJSONAnnotationOpt(eq.comment.annotation_, node, {"Line"}, false, JSON.makeNull());
369 ✗ if not JSON.isNull(e) then
370 ✗ connections := JSON.addElement(e, connections);
371 end if;
372 then ();
373
374 else ();
375 end match;
376 end for;
377 end dumpJSONDiagramParts;
378
379 public function builtinSCode
380 "The builtin classes every top scope needs, so a caller assembling a universe
381 from separately translated libraries prepends them once."
382 output SCode.Program program;
383 algorithm
384 ✗ (_, program) := FBuiltin.getInitialFunctions();
385 end builtinSCode;
386
387 public function builtinAbsyn
388 "The builtin classes as they were parsed, for a caller documenting the
389 OpenModelica package the compiler defines rather than instantiating it."
390 output Absyn.Program program;
391 algorithm
392 ✗ (program, _) := FBuiltin.getInitialFunctions();
393 end builtinAbsyn;
394
395 public function programSCode
396 "One program's SCode. translateAbsyn2SCode carries nothing between top-level
397 classes, so a caller holding many libraries may translate each separately
398 and concatenate the results."
399 input Absyn.Program absynProgram;
400 output SCode.Program program;
401 algorithm
402 ✗ program := AbsynToSCode.translateAbsyn2SCode(absynProgram);
403 end programSCode;
404
405 public function topFromSCode
406 "A fresh top scope over already translated SCode, bypassing mkTop's reuse
407 cache. Fresh is the point: what a scope expands is released when it is
408 dropped, so a batch caller makes a new one per library instead of sharing one
409 and growing without bound."
410 input SCode.Program program;
411 output InstNode top;
412 protected
413 SCode.Program graphicProgramSCode;
414 algorithm
415 ✗ graphicProgramSCode :=
416 AbsynToSCode.translateAbsyn2SCode(annotationProgram(Config.getAnnotationVersion()));
417 ✗ Inst.resetGlobalFlags();
418 ✗ top := NFInst.makeTopNode(program, graphicProgramSCode);
419 end topFromSCode;
420
421 function diagramComponentIcon
422 "The icon dump of a class one of a diagram's components has. A library draws
423 the same few dozen types across thousands of diagrams, and each dump can cost
424 an instantiation, so they are kept for as long as the top scope they belong
425 to.
426
427 Keying by the class' full path is exact rather than approximate here: the
428 node was reached by looking the type name up and expanding it, without the
429 component's own modifications, so the dump depends on the class alone."
430 input InstNode ty_node;
431 output JSON json;
432 protected
433 Option<UnorderedMap<String, JSON>> cached;
434 UnorderedMap<String, JSON> cache;
435 String key;
436 algorithm
437 ✗ cached := getGlobalRoot(Global.nfDiagramIconCache);
438 cache := match cached
439 case SOME(cache) then cache;
440 else
441 algorithm
442 ✗ cache := UnorderedMap.new<JSON>(stringHashDjb2, stringEq);
443 ✗ setGlobalRoot(Global.nfDiagramIconCache, SOME(cache));
444 then
445 cache;
446 end match;
447
448 ✗ key := AbsynUtil.pathString(InstNode.fullPath(ty_node));
449 json := match UnorderedMap.get(key, cache)
450 case SOME(json) then json;
451 else
452 algorithm
453 ✗ json := dumpJSONInstanceAnnotation(ty_node, {"Icon"}, dumpDerivedBase = true);
454 ✗ UnorderedMap.add(key, json, cache);
455 then
456 json;
457 end match;
458 end diagramComponentIcon;
459
460 public function resolveNamesFromTop
461 "What the type references of one class denote, fully qualified, as pairs of
462 the name as written and the name it resolves to: the `extends` clauses and
463 the base of a short class definition in `bases`, the components' types in
464 `componentTypes` keyed by component name.
465
466 This is the frontend's own lookup -- enclosing scopes, then base classes,
467 then imports, with redeclares applied -- rather than a documentation
468 generator's approximation of it. Pairs rather than a bare list so the caller
469 matches on the name instead of trusting two orderings to agree."
470 input InstNode top;
471 input Absyn.Path classPath;
472 output list<tuple<String, String>> bases = {};
473 output list<tuple<String, String>> componentTypes = {};
474 protected
475 InstNode cls_node;
476 InstContext.Type context;
477 SCode.Element def;
478 SCode.ClassDef cdef;
479 Absyn.Path reference;
480 algorithm
481 ✗ context := InstContext.set(NFInstContext.RELAXED, NFInstContext.CLASS);
482 ✗ context := InstContext.set(context, NFInstContext.INSTANCE_API);
483
484 try
485 ✗ cls_node := Inst.lookupRootClass(classPath, top, context);
486 ✗ cls_node := InstNode.resolveInner(cls_node);
487 ✗ cls_node := Inst.expand(cls_node, context);
488 ✗ def := InstNode.definition(cls_node);
489 else
490 ✗ return;
491 end try;
492
493 // A short class definition names its base in the class definition itself
494 // rather than in an extends element.
495 ✗ cdef := SCodeUtil.getClassDef(def);
496 () := match cdef
497 case SCode.ClassDef.DERIVED()
498 algorithm
499 ✗ reference := AbsynUtil.typeSpecPath(cdef.typeSpec);
500 ✗ bases := resolveOne(reference, cls_node, context, SCodeUtil.elementInfo(def)) :: bases;
501 then ();
502 else ();
503 end match;
504
505 ✗ for el in SCodeUtil.getClassElements(def) loop
506 () := match el
507 case SCode.Element.EXTENDS()
508 algorithm
509 ✗ bases := resolveOne(el.baseClassPath, cls_node, context, el.info) :: bases;
510 then ();
511
512 case SCode.Element.COMPONENT()
513 algorithm
514 ✗ reference := AbsynUtil.typeSpecPath(el.typeSpec);
515 ✗ componentTypes :=
516 (el.name, Util.tuple22(resolveOne(reference, cls_node, context, el.info)))
517 :: componentTypes;
518 then ();
519
520 else ();
521 end match;
522 end for;
523
524 ✗ bases := listReverseInPlace(bases);
525 ✗ componentTypes := listReverseInPlace(componentTypes);
526 end resolveNamesFromTop;
527
528 function resolveOne
529 "The name as written, and what it resolves to -- empty when it does not."
530 input Absyn.Path reference;
531 input InstNode scope;
532 input InstContext.Type context;
533 input SourceInfo info;
534 output tuple<String, String> resolved;
535 protected
536 InstNode node;
537 String qualified;
538 algorithm
539 try
540 ✗ node := Lookup.lookupClassName(reference, scope, context, info);
541 ✗ node := Inst.expand(node, context);
542 ✗ qualified := AbsynUtil.pathString(InstNode.fullPath(node));
543 else
544 qualified := "";
545 end try;
546 ✗ resolved := (AbsynUtil.pathString(reference), qualified);
547 end resolveOne;
548
549 public function clearTopScopeCache
550 "Drop everything the last instantiation owns, so a batch caller can release a
551 library when it is done with it. NF nodes refer upwards weakly: what owns
552 them is `nfTopScope` and MutableWeak's set of identity cells, and makeTopNode
553 replaces those only at the next instantiation."
554 algorithm
555 6 setGlobalRoot(Global.instNFNodeCacheIndex, {});
556 6 setGlobalRoot(Global.nfTopScope, {});
557 6 setGlobalRoot(Global.nfDiagramIconCache, NONE());
558 6 MutableWeak.clearRoots();
559 end clearTopScopeCache;
560
561 public function iconJSONFromTop
562 "The icon dump for one class of an already built top scope. A caller doing a
563 whole library — the documentation generator — builds `top` once and keeps it,
564 rather than depending on mkTop's referenceEq cache holding across calls, and
565 drops it when the library is done."
566 input InstNode top;
567 input Absyn.Path classPath;
568 output JSON json;
569 protected
570 InstNode cls_node;
571 InstContext.Type context;
572 algorithm
573 15 context := InstContext.set(NFInstContext.RELAXED, NFInstContext.CLASS);
574 15 context := InstContext.set(context, NFInstContext.INSTANCE_API);
575
576 15 cls_node := Inst.lookupRootClass(classPath, top, context);
577 15 cls_node := InstNode.resolveInner(cls_node);
578
579 15 json := dumpJSONInstanceAnnotation(cls_node, {"Icon"}, dumpConnectors = true, dumpDerivedBase = true);
580 end iconJSONFromTop;
581
582 15 public function storeModelInstanceReference
583 "Stores a boxed JSON value and returns a 1-based handle (0 on failure)."
584 input JSON json;
585 output Integer handle;
586 external "C" handle = ModelInstanceReference_store(json) annotation(Library = "omcruntime");
587 end storeModelInstanceReference;
588
589 15 public function releaseModelInstanceReferenceImpl
590 input Integer handle;
591 output Boolean success;
592 external "C" success = ModelInstanceReference_release(handle) annotation(Library = "omcruntime");
593 end releaseModelInstanceReferenceImpl;
594
595 function parseModifier
596 input String modifierValue;
597 input InstNode scope;
598 output Modifier outMod;
599 protected
600 Absyn.Modification amod;
601 SCode.Mod smod;
602 algorithm
603 try
604 // stringMod parses a single modifier ("x(start = 1) = 2"), but here we want
605 // to parse just a class modifier ("(x = 1, y = 2)"). So we add a dummy name
606 // to the string and then extract the modifier from the ElementArg.
607
4/6
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 48 times.
✓ Branch 6 taken 47 times.
✓ Branch 7 taken 1 time.
48 Absyn.ElementArg.MODIFICATION(modification = SOME(amod)) :=
608 Parser.stringMod("dummy" + modifierValue);
609
610 // Then translate the Absyn mod to a Modifier, using the given scope (it
611 // doesn't matter much which scope it is, it just needs some scope or the
612 // instantiation will fail later).
613 1 smod := AbsynToSCode.translateMod(SOME(amod),
614 SCode.Final.NOT_FINAL(), SCode.Each.NOT_EACH(), NONE(), Absyn.dummyInfo);
615 1 outMod := Modifier.create(smod, "", NFModifier.ModifierScope.COMPONENT(""), scope, 0);
616 else
617 outMod := Modifier.NOMOD();
618 end try;
619 end parseModifier;
620
621 function buildInstanceTree
622 input InstNode node;
623 input Boolean isDerived = false;
624 output InstanceTree tree;
625 protected
626 InstNode cls_node;
627 Class cls;
628 ClassTree cls_tree;
629 list<InstanceTree> elems;
630 algorithm
631 168 cls_node := InstNode.resolveInner(node);
632 168 cls := InstNode.getClass(cls_node);
633
634
5/6
✓ Branch 0 taken 149 times.
✓ Branch 1 taken 19 times.
✓ Branch 3 taken 61 times.
✓ Branch 4 taken 88 times.
✓ Branch 6 taken 61 times.
✗ Branch 7 not taken.
168 if not isDerived and Class.isOnlyBuiltin(cls) and not Class.isEnumeration(cls) then
635 tree := InstanceTree.EMPTY();
636 61 return;
637 end if;
638
639 107 cls_tree := Class.classTree(cls);
640
641 tree := match (cls, cls_tree)
642 case (Class.EXPANDED_DERIVED(), _)
643 algorithm
644 10 elems := {buildInstanceTree(cls.baseClass, isDerived = true)};
645
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 time.
19 then
646 InstanceTree.CLASS(node, elems, isDerived);
647
648 case (_, ClassTree.INSTANTIATED_TREE())
649 algorithm
650 92 elems := buildInstanceTreeElements(InstNode.definition(cls_node), cls_tree);
651
652
2/2
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 46 times.
92 if InstNode.isRootClass(node) then
653 46 elems := buildInstanceTreeGeneratedInners(cls_tree, elems);
654 end if;
655
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 13 times.
171 then
656 InstanceTree.CLASS(node, elems, isDerived);
657
658 case (_, ClassTree.FLAT_TREE())
659
3/4
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
9 then InstanceTree.CLASS(node, if InstNode.isEnumerationType(cls_node) then {ENUM_BASE} else {}, isDerived);
660
661 else
662 algorithm
663 ✗ Error.terminate(getInstanceName() + " got unknown class tree", sourceInfo());
664 ✗ then
665 fail();
666 end match;
667 end buildInstanceTree;
668
669 function buildInstanceTreeElements
670 input SCode.Element classDefinition;
671 input ClassTree classTree;
672 output list<InstanceTree> elements = {};
673 protected
674 list<SCode.Element> scode_elems;
675 array<Mutable<InstNode>> clss, comps;
676 array<InstNode> exts;
677 Integer cls_index = 1, comp_index = 1, ext_index = 1;
678 InstanceTree tree;
679 list<Integer> local_comps;
680 InstNode node;
681 algorithm
682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 92 times.
92 ClassTree.INSTANTIATED_TREE(classes = clss, components = comps, exts = exts,
683 localComponents = local_comps) := classTree;
684 92 scode_elems := SCodeUtil.getClassElements(classDefinition);
685
686
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 21 times.
92 if not listEmpty(local_comps) then
687 71 comp_index :: local_comps := local_comps;
688 end if;
689
690
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 92 times.
227 for e in scode_elems loop
691 elements := match e
692 case SCode.Element.EXTENDS()
693 algorithm
694 9 tree := buildInstanceTree(exts[ext_index], isDerived = true);
695 9 ext_index := ext_index + 1;
696 then
697 tree :: elements;
698
699 case SCode.Element.CLASS()
700 guard SCodeUtil.isElementReplaceable(e)
701 algorithm
702
2/4
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 11 times.
11 while InstNode.name(Mutable.access(clss[cls_index])) <> e.name loop
703 ✗ cls_index := cls_index + 1;
704 end while;
705
706 11 tree := InstanceTree.CLASS(Mutable.access(clss[cls_index]), {}, false);
707 11 cls_index := cls_index + 1;
708 then
709 tree :: elements;
710
711 case SCode.Element.COMPONENT()
712 algorithm
713 1 while true loop
714 108 node := Mutable.access(comps[comp_index]);
715
716
4/6
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 108 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 time.
✓ Branch 9 taken 107 times.
108 if InstNode.name(node) == e.name and not InstNode.isGeneratedInner(node) then
717 break;
718 end if;
719
720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 comp_index :: local_comps := local_comps;
721 end while;
722 //while InstNode.name(Mutable.access(comps[comp_index])) <> e.name loop
723 // comp_index :: local_comps := local_comps;
724 //end while;
725
726 107 tree := buildInstanceTreeComponent(node);
727 elements := tree :: elements;
728
729
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 71 times.
107 if not listEmpty(local_comps) then
730 36 comp_index :: local_comps := local_comps;
731 end if;
732 then
733 elements;
734
735 else elements;
736 end match;
737 end for;
738
739 92 elements := listReverseInPlace(elements);
740 end buildInstanceTreeElements;
741
742 function buildInstanceTreeGeneratedInners
743 input ClassTree classTree;
744 input list<InstanceTree> elements;
745 output list<InstanceTree> outElements;
746 protected
747 array<Mutable<InstNode>> comps;
748 list<InstanceTree> elems = {};
749 algorithm
750
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 46 times.
46 ClassTree.INSTANTIATED_TREE(components = comps) := classTree;
751
752
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 5 times.
47 for i in arrayLength(comps):-1:1 loop
753
2/2
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 41 times.
42 if InstNode.isGeneratedInner(Mutable.access(comps[i])) then
754 1 elems := buildInstanceTreeComponent(Mutable.access(comps[i])) :: elems;
755 else
756 break;
757 end if;
758 end for;
759
760
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 45 times.
46 if listEmpty(elems) then
761 outElements := elements;
762 else
763 1 outElements := listAppend(elements, elems);
764 end if;
765 end buildInstanceTreeGeneratedInners;
766
767 function buildInstanceTreeComponent
768 input InstNode node;
769 output InstanceTree tree;
770 protected
771 InstNode inner_node, cls_node;
772 InstanceTree cls;
773 Binding binding;
774 Option<Binding> opt_binding;
775 algorithm
776 108 inner_node := InstNode.resolveOuter(node);
777 108 cls_node := InstNode.classScope(inner_node);
778
779
2/2
✓ Branch 1 taken 101 times.
✓ Branch 2 taken 7 times.
108 if InstNode.isEmpty(cls_node) then
780 cls := InstanceTree.EMPTY();
781 else
782 101 cls := buildInstanceTree(cls_node);
783 end if;
784
785
1/2
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
108 if InstNode.isComponent(inner_node) then
786 108 binding := Component.getBinding(InstNode.component(inner_node));
787
2/2
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 72 times.
108 opt_binding := if Binding.isBound(binding) then SOME(binding) else NONE();
788 else
789 opt_binding := NONE();
790 end if;
791
792 108 tree := InstanceTree.COMPONENT(node, opt_binding, cls);
793 end buildInstanceTreeComponent;
794
795 function dumpJSONInstanceTree
796 input InstanceTree tree;
797 input InstNode scope;
798 input Boolean root = true;
799 input Boolean isDeleted = false;
800 input Boolean isExtends = false;
801 output JSON json = JSON.makeNull();
802 protected
803 InstNode node;
804 list<InstanceTree> elems;
805 Sections sections;
806 Option<SCode.Comment> cmt;
807 SCode.Element def;
808 algorithm
809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102 times.
102 InstanceTree.CLASS(node = node, elements = elems) := tree;
810 102 node := InstNode.resolveOuter(node);
811 102 def := InstNode.definition(node);
812 102 cmt := SCodeUtil.getElementComment(def);
813
814 102 json := JSON.addPair("name", dumpJSONNodePath(node), json);
815
816 102 json := JSON.addPairNotNull("dims", dumpJSONClassDims(node, def), json);
817 102 json := JSON.addPair("restriction",
818 JSON.makeString(SCodeDump.restrictionStringPP(SCodeUtil.getClassRestriction(def))), json);
819
820 102 json := JSON.addPairNotNull("prefixes", dumpJSONClassPrefixes(def, InstNode.parent(node)), json);
821
822 102 json := dumpJSONCommentOpt(cmt, scope, json);
823
824 102 json := JSON.addPairNotNull("elements", dumpJSONElements(elems, node, isDeleted), json);
825
826
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 2 times.
102 if not isDeleted then
827 100 json := dumpJSONImports(node, json);
828 100 sections := Class.getSections(InstNode.getClass(node));
829 100 json := dumpJSONEquations(sections, node, json);
830 end if;
831
832 102 json := JSON.addPair("source", JSON.dumpJSONSourceInfo(InstNode.info(node)), json);
833 end dumpJSONInstanceTree;
834
835 function dumpJSONInstanceAnnotation
836 input InstNode node;
837 input list<String> filter;
838 input Boolean dumpConnectors = false "the class' own connector components";
839 input Boolean dumpDerivedBase = false "a short class definition's base class";
840 output JSON json = JSON.makeNull();
841 protected
842 Option<SCode.Comment> cmt;
843 SCode.Annotation ann;
844 JSON j;
845 InstNode scope = node;
846 InstContext.Type context;
847 Boolean annotation_is_literal = true;
848 Boolean any_element = false;
849 SCode.Element def;
850 Class cls;
851 algorithm
852 48 Inst.expand(node, NFInstContext.RELAXED);
853 48 def := InstNode.definition(node);
854 48 json := JSON.addPair("name", dumpJSONNodePath(node), json);
855
856 48 json := JSON.addPair("restriction",
857 JSON.makeString(Restriction.toString(InstNode.restriction(node))), json);
858
859 48 json := JSON.addPairNotNull("prefixes", dumpJSONClassPrefixes(def, InstNode.parent(node)), json);
860
861 48 cls := InstNode.getClass(node);
862 48 j := JSON.emptyArray();
863
864 // Class.classTree looks through a derived class, so its extends array is the
865 // base's: listing both would count the base's chain twice.
866
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 7 times.
48 if dumpDerivedBase then
867 () := match cls
868 case Class.EXPANDED_DERIVED()
869 algorithm
870 ✗ j := JSON.addElement(dumpJSONInstanceAnnotationExtends(cls.baseClass, filter, true), j);
871 ✗ any_element := true;
872 then ();
873
874 case Class.TYPED_DERIVED()
875 algorithm
876 ✗ j := JSON.addElement(dumpJSONInstanceAnnotationExtends(cls.baseClass, filter, true), j);
877 ✗ any_element := true;
878 then ();
879
880 else ();
881 end match;
882 end if;
883
884
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if not any_element then
885
2/2
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 48 times.
105 for ext in ClassTree.getExtends(Class.classTree(cls)) loop
886 9 j := JSON.addElement(dumpJSONInstanceAnnotationExtends(ext, filter, dumpDerivedBase), j);
887 9 any_element := true;
888 end for;
889 end if;
890
891
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 33 times.
48 if dumpConnectors then
892 15 (j, any_element) := dumpJSONInstanceAnnotationConnectors(node, j, any_element);
893 end if;
894
895
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 39 times.
48 if any_element then
896 9 json := JSON.addPair("elements", j, json);
897 end if;
898
899 48 cmt := SCodeUtil.getElementComment(InstNode.definition(node));
900
901 cmt := match cmt
902 case SOME(SCode.Comment.COMMENT(annotation_ = SOME(ann as SCode.Annotation.ANNOTATION())))
903 algorithm
904
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 4 times.
34 if not listEmpty(filter) then
905 60 ann.modification := SCodeUtil.filterSubMods(ann.modification,
906 function SCodeUtil.filterGivenSubModNames(namesToKeep = filter));
907 end if;
908
909 34 annotation_is_literal := SCodeUtil.onlyLiteralsInMod(ann.modification);
910
2/2
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 4 times.
64 then
911 if SCodeUtil.isEmptyMod(ann.modification) then NONE() else SOME(SCode.Comment.COMMENT(SOME(ann), NONE()));
912
913 else NONE();
914 end match;
915
916 // Instantiate the scope if the annotation contains component references that
917 // we need to be able to look up.
918
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 33 times.
34 if not annotation_is_literal then
919 1 ErrorExt.setCheckpoint(getInstanceName());
920 try
921 1 context := InstContext.set(NFInstContext.CLASS, NFInstContext.RELAXED);
922 1 scope := InstNode.makeRootClass(scope);
923 1 scope := Inst.instantiate(scope, context = context, instPartial = true);
924 1 Inst.insertGeneratedInners(scope, InstNode.topScope(scope), context);
925 1 Inst.instExpressions(scope, context = context, settings = NFInst.DEFAULT_SETTINGS);
926 else
927 end try;
928 1 ErrorExt.rollBack(getInstanceName());
929 end if;
930
931 48 json := dumpJSONCommentOpt(cmt, scope, json, failOnError = true);
932 end dumpJSONInstanceAnnotation;
933
934 function dumpJSONInstanceAnnotationConnectors
935 "One element per locally declared connector component: name, Placement and
936 the type's icon annotation. A model instance nests the inherited ones under
937 the extends element, so only the class' own belong here."
938 input InstNode node;
939 input output JSON json;
940 input output Boolean any;
941 protected
942 InstContext.Type context = InstContext.set(NFInstContext.RELAXED, NFInstContext.CLASS);
943 InstNode ty_node;
944 JSON e;
945 algorithm
946
2/2
✓ Branch 2 taken 109 times.
✓ Branch 3 taken 15 times.
124 for el in SCodeUtil.getClassElements(InstNode.definition(node)) loop
947 () := match el
948 case SCode.Element.COMPONENT()
949 algorithm
950 try
951 104 ty_node := Lookup.lookupClassName(AbsynUtil.typeSpecPath(el.typeSpec), node, context, el.info);
952
953
2/2
✓ Branch 3 taken 21 times.
✓ Branch 4 taken 83 times.
104 if SCodeUtil.isConnector(SCodeUtil.getClassRestriction(InstNode.definition(ty_node))) then
954 21 ty_node := Inst.expand(ty_node, context);
955 21 e := JSON.addPair("$kind", JSON.STRING("component"), JSON.makeNull());
956 21 e := JSON.addPair("name", JSON.makeString(el.name), e);
957 21 e := dumpJSONAnnotationOpt(el.comment.annotation_, node, {"Placement"}, false, e);
958 21 e := JSON.addPair("type",
959 dumpJSONInstanceAnnotation(ty_node, {"Icon"}, dumpDerivedBase = true), e);
960 21 json := JSON.addElement(e, json);
961 any := true;
962 end if;
963 else
964 end try;
965 then ();
966
967 else ();
968 end match;
969 end for;
970 end dumpJSONInstanceAnnotationConnectors;
971
972 function dumpJSONInstanceAnnotationExtends
973 input InstNode ext;
974 input list<String> filter;
975 input Boolean dumpDerivedBase = false;
976 output JSON json = JSON.makeNull();
977 algorithm
978 9 json := JSON.addPair("$kind", JSON.STRING("extends"), json);
979 9 json := JSON.addPair("baseClass",
980 dumpJSONInstanceAnnotation(ext, filter, dumpDerivedBase = dumpDerivedBase), json);
981 end dumpJSONInstanceAnnotationExtends;
982
983 function dumpJSONNodePath
984 input InstNode node;
985 input Boolean ignoreBaseClass = false;
986 output JSON json = dumpJSONPath(InstNode.enclosingScopePath(node, ignoreBaseClass = ignoreBaseClass));
987 end dumpJSONNodePath;
988
989 function dumpJSONNodeEnclosingPath
990 input InstNode node;
991 output JSON json = dumpJSONPath(InstNode.enclosingScopePath(node, ignoreRedeclare = true));
992 end dumpJSONNodeEnclosingPath;
993
994 function dumpJSONPath
995 input Absyn.Path path;
996 output JSON json = JSON.makeString(AbsynUtil.pathString(path));
997 end dumpJSONPath;
998
999 function dumpJSONElements
1000 input list<InstanceTree> elements;
1001 input InstNode scope;
1002 input Boolean isDeleted;
1003 output JSON json = JSON.makeNull();
1004 protected
1005 JSON j;
1006 algorithm
1007
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 2 times.
103 if isDeleted then
1008
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 for e in elements loop
1009 j := match e
1010 1 case InstanceTree.CLASS(isExtends = true) then dumpJSONExtends(e, isDeleted);
1011 2 else JSON.makeNull();
1012 end match;
1013
1014 3 json := JSON.addElementNotNull(j, json);
1015 end for;
1016 else
1017
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 101 times.
237 for e in elements loop
1018 j := match e
1019 18 case InstanceTree.CLASS(isExtends = true) then dumpJSONExtends(e, isDeleted);
1020 11 case InstanceTree.CLASS() then dumpJSONReplaceableClass(e.node, scope);
1021 106 case InstanceTree.COMPONENT() then dumpJSONComponent(e.node, e.binding, e.cls);
1022 1 case InstanceTree.BUILTIN_BASE_CLASS() then dumpJSONBuiltinBaseClass(e.name);
1023 ✗ else JSON.makeNull();
1024 end match;
1025
1026 136 json := JSON.addElementNotNull(j, json);
1027 end for;
1028 end if;
1029 end dumpJSONElements;
1030
1031 function dumpJSONExtends
1032 input InstanceTree ext;
1033 input Boolean isDeleted;
1034 output JSON json = JSON.makeNull();
1035 protected
1036 InstNode node;
1037 Class cls;
1038 SCode.Element cls_def, ext_def;
1039 algorithm
1040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 InstanceTree.CLASS(node = node) := ext;
1041 19 cls_def := InstNode.definition(node);
1042
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
19 SOME(ext_def) := InstNode.extendsDefinition(node);
1043
1044 19 json := JSON.addPair("$kind", JSON.STRING("extends"), json);
1045 19 json := dumpJSONSCodeMod(getExtendsModifier(ext_def, node), node, json);
1046 19 json := dumpJSONCommentOpt(SCodeUtil.getElementComment(ext_def), node, json);
1047
1048 19 cls := InstNode.getClass(node);
1049
4/4
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 14 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 1 time.
19 if Class.isOnlyBuiltin(cls) and not Class.isEnumeration(cls) then
1050 4 json := JSON.addPair("baseClass", JSON.makeString(InstNode.name(node)), json);
1051 else
1052 15 json := JSON.addPair("baseClass", dumpJSONInstanceTree(ext, node, root = false, isDeleted = isDeleted, isExtends = true), json);
1053 end if;
1054 end dumpJSONExtends;
1055
1056 function dumpJSONBuiltinBaseClass
1057 input String name;
1058 output JSON json = JSON.makeNull();
1059 algorithm
1060 1 json := JSON.addPair("$kind", JSON.STRING("extends"), json);
1061 1 json := JSON.addPair("baseClass", JSON.makeString(name), json);
1062 end dumpJSONBuiltinBaseClass;
1063
1064 function getExtendsModifier
1065 input SCode.Element definition;
1066 input InstNode node;
1067 output SCode.Mod mod;
1068 algorithm
1069 mod := match definition
1070 9 case SCode.EXTENDS() then definition.modifications;
1071 10 case SCode.CLASS() then SCodeUtil.elementMod(InstNode.definition(InstNode.getDerivedNode(node, recursive = false)));
1072 else SCode.NOMOD();
1073 end match;
1074 end getExtendsModifier;
1075
1076 function dumpJSONReplaceableClass
1077 input InstNode cls;
1078 input InstNode scope;
1079 output JSON json = JSON.makeNull();
1080 protected
1081 SCode.Element elem;
1082 InstNode node;
1083 algorithm
1084 11 node := InstNode.getRedeclaredNode(cls);
1085 11 elem := InstNode.definition(node);
1086 11 json := dumpJSONSCodeClass(elem, scope, node, true, json);
1087 11 json := JSON.addPair("source", JSON.dumpJSONSourceInfo(InstNode.info(node)), json);
1088 end dumpJSONReplaceableClass;
1089
1090 function dumpJSONComponent
1091 input InstNode component;
1092 input Option<Binding> originalBinding;
1093 input InstanceTree cls;
1094 output JSON json = JSON.makeNull();
1095 protected
1096 InstNode node, scope, ty_node;
1097 Component comp;
1098 SCode.Element elem;
1099 Boolean is_constant;
1100 Absyn.Path path;
1101 algorithm
1102 106 node := InstNode.resolveOuter(component);
1103 106 comp := InstNode.component(node);
1104 106 elem := InstNode.definition(node);
1105 106 scope := InstNode.parent(node);
1106
1107 106 json := JSON.addPair("$kind", JSON.STRING("component"), json);
1108 106 json := JSON.addPair("name", JSON.makeString(InstNode.name(node)), json);
1109
1110 () := match (comp, elem)
1111 case (Component.COMPONENT(), SCode.Element.COMPONENT())
1112 guard Component.isDeleted(comp)
1113 algorithm
1114 1 json := JSON.addPair("type", dumpJSONComponentType(cls, node, comp.ty, isDeleted = true), json);
1115 1 json := dumpJSONSCodeMod(elem.modifications, scope, json);
1116 1 json := JSON.addPair("condition", JSON.makeBoolean(false), json);
1117 1 json := JSON.addPairNotNull("prefixes", dumpJSONAttributes(elem.attributes, elem.prefixes, scope), json);
1118 1 json := dumpJSONComment(elem.comment, scope, json);
1119 then
1120 ();
1121
1122 case (Component.INVALID_COMPONENT(), SCode.Element.COMPONENT())
1123 algorithm
1124 ✗ json := JSON.addPair("type", dumpJSONComponentType(cls, node, Component.getType(comp)), json);
1125 ✗ json := dumpJSONSCodeMod(elem.modifications, scope, json);
1126 ✗ json := JSON.addPairNotNull("prefixes", dumpJSONAttributes(elem.attributes, elem.prefixes, scope), json);
1127 ✗ json := dumpJSONComment(elem.comment, scope, json);
1128 ✗ json := JSON.addPair("$error", JSON.makeString(comp.errors), json);
1129 then
1130 ();
1131
1132 case (Component.COMPONENT(), SCode.Element.COMPONENT())
1133 algorithm
1134 101 json := JSON.addPair("type", dumpJSONComponentType(cls, node, comp.ty), json);
1135
1136
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 95 times.
101 if Type.isArray(comp.ty) then
1137 6 json := JSON.addPair("dims",
1138 dumpJSONDims(elem.attributes.arrayDims, Type.arrayDims(comp.ty)), json);
1139 end if;
1140
1141 101 json := dumpJSONSCodeMod(elem.modifications, scope, json);
1142
1143
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 77 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
101 is_constant := comp.attributes.variability <= Variability.PARAMETER and
1144 Binding.purity(comp.binding) == Purity.PURE;
1145
2/2
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 65 times.
101 if Binding.isExplicitlyBound(comp.binding) then
1146 36 json := JSON.addPair("value", dumpJSONBinding(comp.binding, originalBinding, evaluate = is_constant), json);
1147 end if;
1148
1149
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 100 times.
101 if Binding.isBound(comp.condition) then
1150 1 json := JSON.addPair("condition", dumpJSONBinding(comp.condition), json);
1151 end if;
1152
1153 101 json := JSON.addPairNotNull("prefixes", dumpJSONAttributes(elem.attributes, elem.prefixes, scope), json);
1154 101 json := dumpJSONComment(comp.comment, scope, json);
1155
1156
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 100 times.
101 if InstNode.isGeneratedInner(node) then
1157 1 json := JSON.addPair("generated", JSON.makeBoolean(true), json);
1158 end if;
1159 then
1160 ();
1161
1162 case (Component.COMPONENT_DEF(), SCode.Element.COMPONENT())
1163 guard AbsynUtil.isOnlyOuter(elem.prefixes.innerOuter)
1164 algorithm
1165 4 path := AbsynUtil.typeSpecPath(elem.typeSpec);
1166
1167 try
1168 4 ty_node := Lookup.lookupName(path, scope, InstContext.set(NFInstContext.RELAXED, NFInstContext.FAST_LOOKUP),
1169 checkAccessViolations = false);
1170 4 json := JSON.addPair("type", dumpJSONSCodeClass(InstNode.definition(ty_node), ty_node, InstNode.resolveInner(component), isRedeclare = false), json);
1171 else
1172 ✗ json := JSON.addPair("type", dumpJSONPath(path), json);
1173 end try;
1174
1175 4 json := JSON.addPairNotNull("prefixes", dumpJSONAttributes(elem.attributes, elem.prefixes, scope), json);
1176 4 json := dumpJSONComment(elem.comment, scope, json);
1177 //json := JSON.addPair("inner", dumpJSONPath(InstNode.scopePath(InstNode.resolveInner(component))), json);
1178 then
1179 ();
1180
1181 else
1182 algorithm
1183 ✗ Error.terminate(getInstanceName() + " got unknown component " +
1184 InstNode.name(node), sourceInfo());
1185 ✗ then
1186 fail();
1187 end match;
1188 end dumpJSONComponent;
1189
1190 function dumpJSONComponentType
1191 input InstanceTree cls;
1192 input InstNode node;
1193 input Type ty;
1194 input Boolean isDeleted = false;
1195 output JSON json;
1196 algorithm
1197 json := match (cls, Type.arrayElementType(ty))
1198 1 case (_, Type.ENUMERATION()) then dumpJSONEnumType(cls, node);
1199 3 case (_, Type.UNKNOWN()) then dumpJSONSCodeElementType(InstNode.definition(node));
1200 39 case (InstanceTree.CLASS(), _) then dumpJSONInstanceTree(cls, node, isDeleted = isDeleted);
1201 59 else dumpJSONTypeName(ty);
1202 end match;
1203 end dumpJSONComponentType;
1204
1205 function dumpJSONSCodeElementType
1206 input SCode.Element elem;
1207 output JSON json = JSON.makeNull();
1208 algorithm
1209 () := match elem
1210 case SCode.Element.COMPONENT()
1211 algorithm
1212 3 json := JSON.addPair("name", dumpJSONPath(AbsynUtil.typeSpecPath(elem.typeSpec)), json);
1213 3 json := JSON.addPair("missing", JSON.makeBoolean(true), json);
1214 then
1215 ();
1216
1217 else ();
1218 end match;
1219 end dumpJSONSCodeElementType;
1220
1221 function dumpJSONEnumType
1222 input InstanceTree tree;
1223 input InstNode enumNode;
1224 output JSON json;
1225 protected
1226 InstNode node = InstNode.resolveInner(InstNode.classScope(enumNode));
1227 SCode.Element def;
1228 array<InstNode> comps;
1229 JSON json_elems;
1230 list<InstanceTree> elems;
1231 algorithm
1232 1 def := InstNode.definition(node);
1233
1234 1 json := JSON.makeNull();
1235 1 json := JSON.addPair("name", dumpJSONNodePath(node), json);
1236 1 json := JSON.addPairNotNull("dims", dumpJSONClassDims(node, def), json);
1237 1 json := JSON.addPair("restriction",
1238 JSON.makeString(SCodeDump.restrictionStringPP(SCodeUtil.getClassRestriction(def))), json);
1239 1 json := dumpJSONCommentOpt(SCodeUtil.getElementComment(def), node, json);
1240
1241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 InstanceTree.CLASS(elements = elems) := tree;
1242 1 json_elems := dumpJSONElements(elems, node, false);
1243
1244 1 comps := ClassTree.getComponents(Class.classTree(InstNode.getClass(node)));
1245 1 json_elems := dumpJSONEnumTypeLiterals(comps, InstNode.parent(node), json_elems);
1246 1 json := JSON.addPair("elements", json_elems, json);
1247
1248 1 json := JSON.addPair("source", JSON.dumpJSONSourceInfo(InstNode.info(node)), json);
1249 end dumpJSONEnumType;
1250
1251 function dumpJSONEnumTypeLiterals
1252 input array<InstNode> literals;
1253 input InstNode scope;
1254 input output JSON json = JSON.emptyArray();
1255 algorithm
1256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
4 for i in 6:arrayLength(literals) loop
1257 3 json := JSON.addElement(dumpJSONEnumTypeLiteral(literals[i], scope), json);
1258 end for;
1259 end dumpJSONEnumTypeLiterals;
1260
1261 function dumpJSONEnumTypeLiteral
1262 input InstNode node;
1263 input InstNode scope;
1264 output JSON json = JSON.makeNull();
1265 algorithm
1266 3 json := JSON.addPair("$kind", JSON.STRING("component"), json);
1267 3 json := JSON.addPair("name", JSON.makeString(InstNode.name(node)), json);
1268 3 json := dumpJSONComment(Component.comment(InstNode.component(node)), scope, json);
1269 end dumpJSONEnumTypeLiteral;
1270
1271 function dumpJSONTypeName
1272 input Type ty;
1273 output JSON json;
1274 algorithm
1275 59 json := JSON.makeString(Type.toString(Type.arrayElementType(ty)));
1276 end dumpJSONTypeName;
1277
1278 function dumpJSONBinding
1279 input Binding binding;
1280 input Option<Binding> originalBinding = NONE();
1281 input Boolean evaluate = true;
1282 output JSON json = JSON.makeNull();
1283 protected
1284 Expression exp;
1285 Binding bind = binding;
1286 InstContext.Type context;
1287 algorithm
1288 // If the binding has been evaluated by the frontend, try to use the original
1289 // binding that we saved when building the instance tree instead.
1290
5/6
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 1 time.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 34 times.
37 if isSome(originalBinding) and Binding.isEvaluated(binding) then
1291 try
1292 2 context := InstContext.set(NFInstContext.RELAXED, NFInstContext.INSTANCE_API);
1293 2 bind := Inst.instBinding(Util.getOption(originalBinding), context);
1294 2 bind := Typing.typeBinding(bind, context);
1295 else
1296 end try;
1297 end if;
1298
1299 37 exp := Binding.getExp(bind);
1300 37 exp := Expression.map(exp, Expression.expandSplitIndices);
1301 37 json := JSON.addPair("binding", Expression.toJSON(exp), json);
1302
1303
4/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 19 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 6 times.
37 if evaluate and not Expression.isLiteral(exp) then
1304 6 ErrorExt.setCheckpoint(getInstanceName());
1305 try
1306 6 exp := Ceval.evalExp(exp, Ceval.EvalTarget.new(Absyn.dummyInfo, NFInstContext.INSTANCE_API));
1307 6 exp := Expression.map(exp, Expression.expandSplitIndices);
1308 6 json := JSON.addPair("value", Expression.toJSON(exp), json);
1309 else
1310 end try;
1311 6 ErrorExt.rollBack(getInstanceName());
1312 end if;
1313 end dumpJSONBinding;
1314
1315 function dumpJSONClassDims
1316 input InstNode node;
1317 input SCode.Element element;
1318 output JSON json;
1319 protected
1320 Type ty;
1321 list<Absyn.Subscript> absyn_dims;
1322 algorithm
1323 103 ty := InstNode.getType(node);
1324
1325
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 103 times.
103 if Type.isArray(ty) then
1326 absyn_dims := match element
1327 case SCode.Element.CLASS(classDef = SCode.ClassDef.DERIVED(typeSpec =
1328 Absyn.TypeSpec.TPATH(arrayDim = SOME(absyn_dims))))
1329 then absyn_dims;
1330
1331 else {};
1332 end match;
1333
1334 ✗ json := dumpJSONDims(absyn_dims, Type.arrayDims(ty));
1335 else
1336 103 json := JSON.makeNull();
1337 end if;
1338 end dumpJSONClassDims;
1339
1340 function dumpJSONDims
1341 input list<Absyn.Subscript> absynDims;
1342 input list<Dimension> typedDims;
1343 output JSON json = JSON.makeNull();
1344 protected
1345 JSON ty_json;
1346 algorithm
1347 7 json := JSON.addPairNotNull("absyn", dumpJSONAbsynDims(absynDims), json);
1348
1349 7 ty_json := JSON.makeNull();
1350
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 7 times.
13 for d in typedDims loop
1351 6 ty_json := JSON.addElement(JSON.makeString(Dimension.toString(d)), ty_json);
1352 end for;
1353
1354 7 json := JSON.addPairNotNull("typed", ty_json, json);
1355 end dumpJSONDims;
1356
1357 function dumpJSONAbsynDims
1358 input list<Absyn.Subscript> dims;
1359 output JSON json = JSON.makeNull();
1360 algorithm
1361
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 7 times.
13 for d in dims loop
1362 6 json := JSON.addElement(JSON.makeString(Dump.printSubscriptStr(d)), json);
1363 end for;
1364 end dumpJSONAbsynDims;
1365
1366 function dumpJSONAttributes
1367 input SCode.Attributes attrs;
1368 input SCode.Prefixes prefs;
1369 input InstNode scope;
1370 output JSON json;
1371 protected
1372 String s;
1373 algorithm
1374 127 json := dumpJSONSCodePrefixes(prefs, scope);
1375
1376 127 s := SCodeDump.connectorTypeStr(attrs.connectorType);
1377
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 123 times.
127 if not stringEmpty(s) then
1378 4 json := JSON.addPair("connector", JSON.makeString(s), json);
1379 end if;
1380
1381 127 s := SCodeDump.unparseVariability(attrs.variability);
1382
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 103 times.
127 if not stringEmpty(s) then
1383 24 json := JSON.addPair("variability", JSON.makeString(s), json);
1384 end if;
1385
1386
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 124 times.
127 if AbsynUtil.isInput(attrs.direction) then
1387 3 json := JSON.addPair("direction", JSON.STRING("input"), json);
1388 elseif AbsynUtil.isOutput(attrs.direction) then
1389 1 json := JSON.addPair("direction", JSON.STRING("output"), json);
1390 end if;
1391 end dumpJSONAttributes;
1392
1393 function dumpJSONSCodePrefixes
1394 input SCode.Prefixes prefixes;
1395 input InstNode scope;
1396 output JSON json = JSON.makeNull();
1397 algorithm
1398
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 274 times.
275 if not SCodeUtil.visibilityBool(prefixes.visibility) then
1399 1 json := JSON.addPair("public", JSON.makeBoolean(false), json);
1400 end if;
1401
1402
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 275 times.
275 if SCodeUtil.finalBool(prefixes.finalPrefix) then
1403 ✗ json := JSON.addPair("final", JSON.makeBoolean(true), json);
1404 end if;
1405
1406
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 270 times.
275 if AbsynUtil.isInner(prefixes.innerOuter) then
1407 5 json := JSON.addPair("inner", JSON.makeBoolean(true), json);
1408 end if;
1409
1410
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 270 times.
275 if AbsynUtil.isOuter(prefixes.innerOuter) then
1411 5 json := JSON.addPair("outer", JSON.makeBoolean(true), json);
1412 end if;
1413
1414 275 json := JSON.addPairNotNull("replaceable",
1415 dumpJSONReplaceable(prefixes.replaceablePrefix, scope), json);
1416
1417
2/2
✓ Branch 1 taken 270 times.
✓ Branch 2 taken 5 times.
275 if SCodeUtil.redeclareBool(prefixes.redeclarePrefix) then
1418 5 json := JSON.addPair("redeclare", JSON.makeBoolean(true), json);
1419 end if;
1420 end dumpJSONSCodePrefixes;
1421
1422 function dumpJSONClassPrefixes
1423 input SCode.Element element;
1424 input InstNode scope;
1425 output JSON json;
1426 protected
1427 SCode.ClassDef cdef;
1428 algorithm
1429 json := match element
1430 case SCode.CLASS(classDef = cdef, prefixes = _)
1431 algorithm
1432 json := match cdef
1433 20 case SCode.ClassDef.DERIVED() then dumpJSONAttributes(cdef.attributes, element.prefixes, scope);
1434 148 else dumpJSONSCodePrefixes(element.prefixes, scope);
1435 end match;
1436
1437
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 161 times.
168 if SCodeUtil.partialBool(element.partialPrefix) then
1438 7 json := JSON.addPair("partial", JSON.makeBoolean(true), json);
1439 end if;
1440
1441
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 168 times.
168 if SCodeUtil.encapsulatedBool(element.encapsulatedPrefix) then
1442 ✗ json := JSON.addPair("encapsulated", JSON.makeBoolean(true), json);
1443 end if;
1444 then
1445 json;
1446
1447 ✗ else JSON.makeNull();
1448 end match;
1449 end dumpJSONClassPrefixes;
1450
1451 function dumpJSONReplaceable
1452 input SCode.Replaceable repl;
1453 input InstNode scope;
1454 output JSON json;
1455 protected
1456 SCode.ConstrainClass cc;
1457 algorithm
1458 json := match repl
1459 case SCode.Replaceable.REPLACEABLE(cc = SOME(cc))
1460 algorithm
1461 4 json := JSON.makeNull();
1462 4 json := JSON.addPair("constrainedby", dumpJSONPath(cc.constrainingClass), json);
1463 4 json := dumpJSONSCodeMod(cc.modifier, scope, json);
1464 4 json := dumpJSONCommentOpt(SOME(cc.comment), scope, json);
1465 then
1466 json;
1467
1468 15 case SCode.Replaceable.REPLACEABLE() then JSON.makeBoolean(true);
1469 256 else JSON.makeNull();
1470 end match;
1471 end dumpJSONReplaceable;
1472
1473 function dumpJSONCommentOpt
1474 input Option<SCode.Comment> cmtOpt;
1475 input InstNode scope;
1476 input output JSON json;
1477 input Boolean dumpComment = true;
1478 input Boolean dumpAnnotation = true;
1479 input Boolean failOnError = false;
1480 algorithm
1481
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 18 times.
174 if isSome(cmtOpt) then
1482 156 json := dumpJSONComment(Util.getOption(cmtOpt), scope, json, dumpComment, dumpAnnotation, failOnError);
1483 end if;
1484 end dumpJSONCommentOpt;
1485
1486 function dumpJSONComment
1487 input SCode.Comment cmt;
1488 input InstNode scope;
1489 input output JSON json;
1490 input Boolean dumpComment = true;
1491 input Boolean dumpAnnotation = true;
1492 input Boolean failOnError = false;
1493 algorithm
1494
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 284 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 277 times.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
284 if isSome(cmt.comment) and dumpComment then
1495 7 json := JSON.addPair("comment", JSON.makeString(Util.getOption(cmt.comment)), json);
1496 end if;
1497
1498
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 273 times.
284 if dumpAnnotation then
1499 273 json := dumpJSONAnnotationOpt(cmt.annotation_, scope, {}, failOnError, json);
1500 end if;
1501 end dumpJSONComment;
1502
1503 function dumpJSONCommentAnnotation
1504 input Option<SCode.Comment> cmtOpt;
1505 input InstNode scope;
1506 input output JSON json;
1507 input list<String> filter = {};
1508 input Boolean failOnError = false;
1509 protected
1510 SCode.Comment cmt;
1511 algorithm
1512
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
15 if isSome(cmtOpt) then
1513 15 SOME(cmt) := cmtOpt;
1514 15 json := dumpJSONAnnotationOpt(cmt.annotation_, scope, filter, failOnError, json);
1515 end if;
1516 end dumpJSONCommentAnnotation;
1517
1518 function dumpJSONAnnotationOpt
1519 input Option<SCode.Annotation> annOpt;
1520 input InstNode scope;
1521 input list<String> filter;
1522 input Boolean failOnError;
1523 input output JSON json;
1524 protected
1525 SCode.Annotation ann;
1526 algorithm
1527
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 240 times.
309 if isSome(annOpt) then
1528 69 SOME(ann) := annOpt;
1529 69 json := JSON.addPair("annotation", dumpJSONAnnotationMod(ann.modification, scope, filter, failOnError), json);
1530 end if;
1531 end dumpJSONAnnotationOpt;
1532
1533 function dumpJSONAnnotationMod
1534 input SCode.Mod mod;
1535 input InstNode scope;
1536 input list<String> filter;
1537 input Boolean failOnError;
1538 output JSON json;
1539 algorithm
1540 json := match mod
1541 case SCode.Mod.MOD()
1542 69 then dumpJSONAnnotationSubMods(mod.subModLst, scope, filter, failOnError);
1543
1544 ✗ else JSON.makeNull();
1545 end match;
1546 end dumpJSONAnnotationMod;
1547
1548 function dumpJSONAnnotationSubMods
1549 input list<SCode.SubMod> subMods;
1550 input InstNode scope;
1551 input list<String> filter;
1552 input Boolean failOnError;
1553 output JSON json = JSON.makeNull();
1554 algorithm
1555
2/2
✓ Branch 0 taken 232 times.
✓ Branch 1 taken 179 times.
411 for m in subMods loop
1556
3/4
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 211 times.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
232 if listEmpty(filter) or List.contains(filter, m.ident, stringEq) then
1557 232 json := dumpJSONAnnotationSubMod(m, scope, failOnError, json);
1558 end if;
1559 end for;
1560 end dumpJSONAnnotationSubMods;
1561
1562 function dumpJSONAnnotationSubMod
1563 input SCode.SubMod subMod;
1564 input InstNode scope;
1565 input Boolean failOnError;
1566 input output JSON json;
1567 protected
1568 String name;
1569 SCode.Mod mod;
1570 Absyn.Exp absyn_binding;
1571 JSON j;
1572 algorithm
1573 233 SCode.SubMod.NAMEMOD(ident = name, mod = mod) := subMod;
1574
1575 () := match (name, mod)
1576 case ("choices", SCode.Mod.MOD())
1577 algorithm
1578 1 j := dumpJSONChoicesAnnotation(mod.subModLst, scope, mod.info, failOnError);
1579 1 json := JSON.addPairNotNull(name, j, json);
1580 then
1581 ();
1582
1583 case (_, SCode.Mod.MOD(binding = SOME(absyn_binding)))
1584 algorithm
1585 121 j := dumpJSONAnnotationExp(absyn_binding, scope, mod.info, failOnError);
1586 121 json := JSON.addPair(name, j, json);
1587 then
1588 ();
1589
1590 case (_, SCode.Mod.MOD())
1591 algorithm
1592 110 json := JSON.addPair(name, dumpJSONAnnotationSubMods(mod.subModLst, scope, {}, failOnError), json);
1593 then
1594 ();
1595
1596 case (_, SCode.Mod.NOMOD())
1597 algorithm
1598 1 json := JSON.addPair(name, JSON.emptyListObject(), json);
1599 then
1600 ();
1601
1602 else ();
1603 end match;
1604 end dumpJSONAnnotationSubMod;
1605
1606 function dumpJSONAnnotationExp
1607 input Absyn.Exp absynExp;
1608 input InstNode scope;
1609 input SourceInfo info;
1610 input Boolean failOnError;
1611 output JSON json;
1612 protected
1613 JSON j;
1614 algorithm
1615 json := match absynExp
1616 19 case Absyn.Exp.INTEGER() then JSON.makeInteger(absynExp.value);
1617 ✗ case Absyn.Exp.REAL() then JSON.makeNumber(stringReal(absynExp.value));
1618 ✗ case Absyn.Exp.STRING() then JSON.makeString(absynExp.value);
1619 33 case Absyn.Exp.BOOL() then JSON.makeBoolean(absynExp.value);
1620
1621 // For non-literal arrays, dump each element separately to avoid
1622 // invalidating the whole array expression if any element contains invalid
1623 // expressions.
1624 case Absyn.Exp.ARRAY()
1625 guard not AbsynUtil.isLiteralExp(absynExp)
1626 algorithm
1627 135 json := JSON.emptyArray(listLength(absynExp.arrayExp));
1628
2/2
✓ Branch 0 taken 242 times.
✓ Branch 1 taken 135 times.
377 for e in absynExp.arrayExp loop
1629 242 j := dumpJSONAnnotationExp(e, scope, info, failOnError);
1630 242 json := JSON.addElement(j, json);
1631 end for;
1632 then
1633 json;
1634
1635 176 else dumpJSONAnnotationExp2(absynExp, scope, info, failOnError);
1636 end match;
1637 end dumpJSONAnnotationExp;
1638
1639 function dumpJSONAnnotationExp2
1640 input Absyn.Exp absynExp;
1641 input InstNode scope;
1642 input SourceInfo info;
1643 input Boolean failOnError;
1644 output JSON json;
1645 protected
1646 Expression exp;
1647 algorithm
1648 176 ErrorExt.setCheckpoint(getInstanceName());
1649 try
1650 176 exp := Inst.instExp(absynExp, scope, INST_API_ANNOTATION_CONTEXT, info);
1651 175 exp := Typing.typeExp(exp, INST_API_ANNOTATION_CONTEXT, info);
1652 175 exp := SimplifyExp.simplify(exp);
1653 175 json := Expression.toJSON(exp);
1654 else
1655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if failOnError then
1656 ✗ fail();
1657 end if;
1658
1659 1 json := JSON.makeNull();
1660 1 json := JSON.addPair("$error", JSON.makeString(ErrorExt.printCheckpointMessagesStr()), json);
1661 1 json := JSON.addPair("value", dumpJSONAbsynExpression(absynExp), json);
1662 end try;
1663 176 ErrorExt.delCheckpoint(getInstanceName());
1664 end dumpJSONAnnotationExp2;
1665
1666
1667
1668 function dumpJSONAbsynExpression
1669 input Absyn.Exp exp;
1670 output JSON json;
1671 protected
1672 Integer i;
1673 String r;
1674 algorithm
1675 json := match exp
1676 3 case Absyn.Exp.INTEGER() then JSON.makeInteger(exp.value);
1677 ✗ case Absyn.Exp.REAL() then JSON.makeNumber(stringReal(exp.value));
1678 1 case Absyn.Exp.CREF() then dumpJSONAbsynCref(exp.componentRef);
1679 ✗ case Absyn.Exp.STRING() then JSON.makeString(exp.value);
1680 ✗ case Absyn.Exp.BOOL() then JSON.makeBoolean(exp.value);
1681
1682 case Absyn.Exp.UNARY(op = Absyn.Operator.UMINUS(), exp = Absyn.Exp.INTEGER(value = i))
1683 ✗ then JSON.makeInteger(-i);
1684
1685 case Absyn.Exp.UNARY(op = Absyn.Operator.UMINUS(), exp = Absyn.Exp.REAL(value = r))
1686 ✗ then JSON.makeNumber(-stringReal(r));
1687
1688 case Absyn.Exp.CALL()
1689 algorithm
1690 1 json := JSON.makeNull();
1691 1 json := JSON.addPair("$kind", JSON.STRING("call"), json);
1692 1 json := JSON.addPair("name", dumpJSONAbsynCref(exp.function_), json);
1693 1 json := dumpJSONAbsynFunctionArgs(exp.functionArgs, json);
1694 then
1695 json;
1696
1697 case Absyn.Exp.ARRAY()
1698 algorithm
1699 3 json := JSON.emptyArray(listLength(exp.arrayExp));
1700
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 for e in exp.arrayExp loop
1701 6 json := JSON.addElement(dumpJSONAbsynExpression(e), json);
1702 end for;
1703 then
1704 json;
1705
1706 ✗ else JSON.makeString(Dump.printExpStr(AbsynUtil.stripCommentExpressions(exp, true)));
1707 end match;
1708 end dumpJSONAbsynExpression;
1709
1710 function dumpJSONAbsynCref
1711 input Absyn.ComponentRef cref;
1712 output JSON json;
1713 algorithm
1714 2 json := JSON.makeString(Dump.printComponentRefStr(cref));
1715 end dumpJSONAbsynCref;
1716
1717 function dumpJSONAbsynFunctionArgs
1718 input Absyn.FunctionArgs args;
1719 input output JSON json;
1720 protected
1721 JSON json_args;
1722 algorithm
1723 () := match args
1724 case Absyn.FunctionArgs.FUNCTIONARGS()
1725 algorithm
1726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if not listEmpty(args.args) then
1727 ✗ json_args := JSON.makeNull();
1728 ✗ for arg in args.args loop
1729 ✗ json_args := JSON.addElement(dumpJSONAbsynExpression(arg), json_args);
1730 end for;
1731
1732 ✗ json := JSON.addPair("args", json_args, json);
1733 end if;
1734
1735
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if not listEmpty(args.argNames) then
1736 1 json_args := JSON.makeNull();
1737
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for arg in args.argNames loop
1738 1 json_args := JSON.addPair(arg.argName, dumpJSONAbsynExpression(arg.argValue), json_args);
1739 end for;
1740
1741 1 json := JSON.addPair("namedArgs", json_args, json);
1742 end if;
1743 then
1744 ();
1745
1746 else ();
1747 end match;
1748 end dumpJSONAbsynFunctionArgs;
1749
1750 function dumpJSONImports
1751 input InstNode node;
1752 input output JSON json;
1753 protected
1754 InstNode n = node;
1755 array<Import> imps;
1756 list<Import> resolved_imps;
1757 JSON json_imp, json_imp_array;
1758 algorithm
1759 100 json_imp_array := JSON.makeNull();
1760
1761
2/2
✓ Branch 1 taken 239 times.
✓ Branch 2 taken 100 times.
339 while not InstNode.isEmpty(n) loop
1762 239 imps := ClassTree.getImports(Class.classTree(InstNode.getClass(n)));
1763
1764
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 236 times.
239 if not arrayEmpty(imps) then
1765 3 resolved_imps := Import.resolveList(imps);
1766 3 resolved_imps := listReverseInPlace(resolved_imps);
1767
1768
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 for imp in resolved_imps loop
1769 () := match imp
1770 case Import.RESOLVED_IMPORT()
1771 algorithm
1772 5 json_imp := JSON.makeNull();
1773 5 json_imp := JSON.addPair("path", dumpJSONPath(InstNode.fullPath(InstNode.borrow(imp.node))), json_imp);
1774
1775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if not stringEmpty(imp.shortName) then
1776 ✗ json_imp := JSON.addPair("shortName", JSON.makeString(imp.shortName), json_imp);
1777 end if;
1778
1779 5 json_imp_array := JSON.addElement(json_imp, json_imp_array);
1780 then
1781 ();
1782
1783 else ();
1784 end match;
1785 end for;
1786 end if;
1787
1788 239 n := InstNode.parent(n);
1789 end while;
1790
1791 100 json := JSON.addPairNotNull("imports", json_imp_array, json);
1792 end dumpJSONImports;
1793
1794 function dumpJSONEquations
1795 input Sections sections;
1796 input InstNode scope;
1797 input output JSON json;
1798 protected
1799 list<Equation> connections, transitions, initial_states;
1800 JSON j;
1801 InstContext.Type context;
1802 algorithm
1803 100 (connections, transitions, initial_states) := sortEquations(Sections.equations(sections));
1804 100 context := InstContext.set(NFInstContext.CLASS, NFInstContext.RELAXED);
1805
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 100 times.
100 transitions := list(Typing.typeEquation(e, context) for e in transitions);
1806
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 100 times.
100 initial_states := list(Typing.typeEquation(e, context) for e in initial_states);
1807
1808 100 j := dumpJSONConnections(connections, scope);
1809 100 json := JSON.addPairNotNull("connections", j, json);
1810
1811 100 j := dumpJSONStateCalls(initial_states, scope);
1812 100 json := JSON.addPairNotNull("initialStates", j, json);
1813
1814 100 j := dumpJSONStateCalls(transitions, scope);
1815 100 json := JSON.addPairNotNull("transitions", j, json);
1816 end dumpJSONEquations;
1817
1818 function sortEquations
1819 input list<Equation> equations;
1820 input output list<Equation> connections = {};
1821 input output list<Equation> transitions = {};
1822 input output list<Equation> initialStates = {};
1823 algorithm
1824
4/7
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 101 times.
106 for eq in listReverse(equations) loop
1825 () := match eq
1826 case Equation.CONNECT()
1827 algorithm
1828 connections := eq :: connections;
1829 then
1830 ();
1831
1832 case Equation.FOR()
1833 algorithm
1834 ✗ (connections, transitions, initialStates) :=
1835 sortEquations(eq.body, connections, transitions, initialStates);
1836 then
1837 ();
1838
1839 case Equation.IF()
1840 algorithm
1841
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for b in eq.branches loop
1842 () := match b
1843 case Equation.Branch.BRANCH()
1844 algorithm
1845 1 (connections, transitions, initialStates) :=
1846 sortEquations(b.body, connections, transitions, initialStates);
1847 then
1848 ();
1849
1850 else ();
1851 end match;
1852 end for;
1853 then
1854 ();
1855
1856 case Equation.NORETCALL()
1857 algorithm
1858 ✗ if Expression.isCallNamed(eq.exp, "transition") then
1859 ✗ transitions := eq :: transitions;
1860 elseif Expression.isCallNamed(eq.exp, "initialState") then
1861 ✗ initialStates := eq :: initialStates;
1862 end if;
1863 then
1864 ();
1865
1866 else ();
1867 end match;
1868 end for;
1869 end sortEquations;
1870
1871 function dumpJSONConnections
1872 input list<Equation> connections;
1873 input InstNode scope;
1874 output JSON json = JSON.makeNull();
1875 algorithm
1876
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 100 times.
104 for conn in connections loop
1877 4 json := JSON.addElement(dumpJSONConnection(conn, scope), json);
1878 end for;
1879 end dumpJSONConnections;
1880
1881 function dumpJSONConnection
1882 input Equation connEq;
1883 input InstNode scope;
1884 output JSON json = JSON.makeNull();
1885 protected
1886 Expression lhs, rhs;
1887 DAE.ElementSource src;
1888 algorithm
1889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 Equation.CONNECT(lhs = lhs, rhs = rhs, source = src) := connEq;
1890 4 json := JSON.addPair("lhs", Expression.toJSON(lhs), json);
1891 4 json := JSON.addPair("rhs", Expression.toJSON(rhs), json);
1892 4 json := dumpJSONCommentAnnotation(ElementSource.getOptComment(src), scope, json);
1893 end dumpJSONConnection;
1894
1895 function dumpJSONStateCalls
1896 input list<Equation> callEqs;
1897 input InstNode scope;
1898 output JSON json = JSON.makeNull();
1899 algorithm
1900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 for eq in callEqs loop
1901 ✗ json := JSON.addElement(dumpJSONStateCall(eq, scope), json);
1902 end for;
1903 end dumpJSONStateCalls;
1904
1905 function dumpJSONStateCall
1906 input Equation callEq;
1907 input InstNode scope;
1908 output JSON json = JSON.makeNull();
1909 protected
1910 Call call;
1911 list<Expression> args;
1912 DAE.ElementSource src;
1913 JSON j;
1914 algorithm
1915 () := match callEq
1916 case Equation.NORETCALL(exp = Expression.CALL(call = call as Call.TYPED_CALL(arguments = args)), source = src)
1917 algorithm
1918 ✗ j := JSON.emptyArray(listLength(args));
1919 ✗ for arg in args loop
1920 ✗ j := JSON.addElement(Expression.toJSON(arg), j);
1921 end for;
1922 ✗ json := JSON.addPair("arguments", j, json);
1923 ✗ json := dumpJSONCommentAnnotation(ElementSource.getOptComment(src), scope, json);
1924 then
1925 ();
1926
1927 else ();
1928 end match;
1929 end dumpJSONStateCall;
1930
1931 function dumpJSONReplaceableElements
1932 input InstNode clsNode;
1933 output JSON json = JSON.makeNull();
1934 protected
1935 ClassTree cls_tree;
1936 JSON j;
1937 algorithm
1938 ✗ cls_tree := Class.classTree(InstNode.getClass(clsNode));
1939
1940 ✗ for c in ClassTree.getComponents(cls_tree) loop
1941 ✗ if InstNode.isReplaceable(c) then
1942 ✗ j := JSON.makeNull();
1943 ✗ j := JSON.addPair("name", JSON.makeString(InstNode.name(c)), j);
1944 ✗ j := JSON.addPair("type", dumpJSONTypeName(InstNode.getType(c)), j);
1945 ✗ json := JSON.addElement(j, json);
1946 end if;
1947 end for;
1948
1949 ✗ for c in ClassTree.getClasses(cls_tree) loop
1950 ✗ if InstNode.isReplaceable(c) then
1951 ✗ json := JSON.addElement(JSON.makeString(InstNode.name(c)), json);
1952 end if;
1953 end for;
1954 end dumpJSONReplaceableElements;
1955
1956 function dumpJSONSCodeMod
1957 input SCode.Mod mod;
1958 input InstNode scope;
1959 input output JSON json;
1960 protected
1961 JSON j;
1962 algorithm
1963 137 j := dumpJSONSCodeMod_impl(mod, scope);
1964 137 json := JSON.addPairNotNull("modifiers", j, json);
1965 end dumpJSONSCodeMod;
1966
1967 function dumpJSONSCodeMod_impl
1968 input SCode.Mod mod;
1969 input InstNode scope;
1970 input Boolean isChoices = false;
1971 output JSON json = JSON.makeNull();
1972 protected
1973 JSON binding_json;
1974 algorithm
1975 () := match mod
1976 case SCode.Mod.MOD()
1977 algorithm
1978
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 62 times.
86 for m in mod.subModLst loop
1979 24 json := JSON.addPair(m.ident, dumpJSONSCodeMod_impl(m.mod, scope), json);
1980 end for;
1981
1982
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 59 times.
62 if SCodeUtil.finalBool(mod.finalPrefix) then
1983 3 json := JSON.addPair("final", JSON.makeBoolean(true), json);
1984 end if;
1985
1986
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 60 times.
62 if SCodeUtil.eachBool(mod.eachPrefix) then
1987 2 json := JSON.addPair("each", JSON.makeBoolean(true), json);
1988 end if;
1989
1990
4/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
62 if isChoices and isSome(mod.comment) then
1991 3 json := JSON.addPair("comment", JSON.makeString(Util.getOption(mod.comment)), json);
1992 end if;
1993
1994
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 17 times.
62 if isSome(mod.binding) then
1995 45 binding_json := JSON.makeString(Dump.printExpStr(AbsynUtil.stripCommentExpressions(Util.getOption(mod.binding), true)));
1996
1997
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 37 times.
45 if JSON.isNull(json) then
1998 json := binding_json;
1999 else
2000 8 json := JSON.addPair("$value", binding_json, json);
2001 end if;
2002 end if;
2003 then
2004 ();
2005
2006 case SCode.Mod.REDECL()
2007 algorithm
2008
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if SCodeUtil.finalBool(mod.finalPrefix) then
2009 ✗ json := JSON.addPair("final", JSON.makeBoolean(true), json);
2010 end if;
2011
2012
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if SCodeUtil.eachBool(mod.eachPrefix) then
2013 ✗ json := JSON.addPair("each", JSON.makeBoolean(true), json);
2014 end if;
2015
2016 4 json := JSON.addPair("$value", dumpJSONSCodeElement(mod.element, scope), json);
2017 then
2018 ();
2019
2020 else ();
2021 end match;
2022 end dumpJSONSCodeMod_impl;
2023
2024 function dumpJSONRedeclareType
2025 input SCode.Element element;
2026 input InstNode scope;
2027 input output JSON json;
2028 protected
2029 Absyn.Path path;
2030 InstContext.Type context;
2031 InstNode cls;
2032 algorithm
2033 () := matchcontinue element
2034 case SCode.Element.COMPONENT()
2035 algorithm
2036 ✗ path := AbsynUtil.typeSpecPath(element.typeSpec);
2037 ✗ context := InstContext.set(NFInstContext.RELAXED, NFInstContext.FAST_LOOKUP);
2038 ✗ cls := Lookup.lookupName(path, scope, context, checkAccessViolations = false);
2039 ✗ json := JSON.addPair("$type", dumpJSONNodePath(cls), json);
2040 then
2041 ();
2042
2043 else ();
2044 end matchcontinue;
2045 end dumpJSONRedeclareType;
2046
2047 function dumpJSONSCodeElement
2048 input SCode.Element element;
2049 input InstNode scope;
2050 input output JSON json = JSON.makeNull();
2051 algorithm
2052 json := match element
2053 case SCode.Element.COMPONENT()
2054 algorithm
2055 1 json := JSON.addPair("$kind", JSON.STRING("component"), json);
2056 1 json := JSON.addPair("name", JSON.makeString(element.name), json);
2057 1 json := JSON.addPair("type", dumpJSONPath(AbsynUtil.typeSpecPath(element.typeSpec)), json);
2058 1 json := JSON.addPairNotNull("dims", dumpJSONDims(element.attributes.arrayDims, {}), json);
2059 1 json := dumpJSONSCodeMod(element.modifications, scope, json);
2060 1 json := JSON.addPairNotNull("prefixes", dumpJSONAttributes(element.attributes, element.prefixes, scope), json);
2061
2062
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 if isSome(element.condition) then
2063 ✗ json := JSON.addPair("condition", dumpJSONAbsynExpression(Util.getOption(element.condition)), json);
2064 end if;
2065
2066 1 json := dumpJSONComment(element.comment, scope, json);
2067 then
2068 json;
2069
2070 case SCode.Element.CLASS()
2071 3 then dumpJSONSCodeClass(element, InstNode.EMPTY_NODE(), scope, false, json);
2072
2073 else json;
2074 end match;
2075 end dumpJSONSCodeElement;
2076
2077 function dumpJSONSCodeType
2078 input Absyn.Path path;
2079 input InstNode scope;
2080 input output JSON json;
2081 protected
2082 InstNode ty_node;
2083 algorithm
2084 try
2085 ✗ ty_node := Lookup.lookupName(path, scope, InstContext.set(NFInstContext.RELAXED, NFInstContext.FAST_LOOKUP),
2086 checkAccessViolations = false);
2087 ✗ json := JSON.addPair("type", dumpJSONSCodeClass(InstNode.definition(ty_node), ty_node, scope, isRedeclare = false), json);
2088 else
2089 ✗ json := JSON.addPair("type", dumpJSONPath(path), json);
2090 end try;
2091 end dumpJSONSCodeType;
2092
2093 function dumpJSONSCodeClass
2094 input SCode.Element element;
2095 input InstNode node;
2096 input InstNode scope;
2097 input Boolean isRedeclare;
2098 input output JSON json = JSON.makeNull();
2099 algorithm
2100 () := match element
2101 case SCode.CLASS()
2102 algorithm
2103 18 json := JSON.addPair("$kind", JSON.STRING("class"), json);
2104
2105
4/4
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 4 times.
18 if InstNode.isEmpty(node) or isRedeclare then
2106 14 json := JSON.addPair("name", JSON.makeString(element.name), json);
2107 else
2108 4 json := JSON.addPair("name", dumpJSONNodeEnclosingPath(node), json);
2109 end if;
2110
2111 18 json := JSON.addPair("restriction",
2112 JSON.makeString(SCodeDump.restrictionStringPP(element.restriction)), json);
2113 18 json := JSON.addPairNotNull("prefixes", dumpJSONClassPrefixes(element, scope), json);
2114 18 json := dumpJSONSCodeClassDef(element.classDef, scope, isRedeclare, json);
2115 18 json := dumpJSONComment(element.cmt, scope, json, dumpAnnotation = not isRedeclare);
2116
2117
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7 times.
18 if isRedeclare then
2118 11 json := dumpJSONCommentAnnotation(SOME(element.cmt), scope, json,
2119 {"Dialog", "choices", "choicesAllMatching"});
2120 end if;
2121
2122
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 11 times.
18 if not isRedeclare then
2123 7 json := dumpJSONSCodeTypeExtends(node, scope, json);
2124 end if;
2125 then
2126 ();
2127 end match;
2128 end dumpJSONSCodeClass;
2129
2130 function dumpJSONSCodeTypeExtends
2131 input InstNode node;
2132 input InstNode scope;
2133 input output JSON json;
2134 protected
2135 InstNode expanded_node;
2136 array<InstNode> exts;
2137 JSON json_elements, json_ext;
2138 algorithm
2139
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 4 times.
7 if InstNode.isEmpty(node) then
2140 3 return;
2141 end if;
2142
2143 try
2144 4 expanded_node := Inst.expand(node, NFInstContext.RELAXED);
2145 4 exts := ClassTree.getExtends(Class.classTree(InstNode.getClass(expanded_node)));
2146
2147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if not arrayEmpty(exts) then
2148 ✗ json_elements := JSON.makeNull();
2149
2150 ✗ for ext in exts loop
2151 ✗ json_ext := JSON.makeNull();
2152 ✗ json_ext := JSON.addPair("$kind", JSON.STRING("extends"), json_ext);
2153 ✗ json_ext := JSON.addPair("baseClass", dumpJSONSCodeClass(InstNode.definition(ext), ext, scope, false), json_ext);
2154 ✗ json_elements := JSON.addElement(json_ext, json_elements);
2155 end for;
2156
2157 ✗ json := JSON.addPair("elements", json_elements, json);
2158 end if;
2159 else
2160 end try;
2161 end dumpJSONSCodeTypeExtends;
2162
2163 function dumpJSONSCodeClassDef
2164 input SCode.ClassDef classDef;
2165 input InstNode scope;
2166 input Boolean qualifyPath;
2167 input output JSON json;
2168 protected
2169 Absyn.Path path;
2170 Option<list<Absyn.Subscript>> odims;
2171 InstNode derivedNode;
2172 algorithm
2173 () := match classDef
2174 case SCode.ClassDef.DERIVED(typeSpec = Absyn.TypeSpec.TPATH(path = path, arrayDim = odims))
2175 algorithm
2176
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 if qualifyPath then
2177 try
2178 8 derivedNode := Lookup.lookupName(path, scope, NFInstContext.RELAXED, false);
2179 8 json := JSON.addPair("baseClass", dumpJSONNodeEnclosingPath(derivedNode), json);
2180 else
2181 end try;
2182 else
2183 3 json := JSON.addPair("baseClass", dumpJSONPath(path), json);
2184 end if;
2185
2186
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if isSome(odims) then
2187 ✗ json := JSON.addPairNotNull("dims", dumpJSONDims(Util.getOption(odims), {}), json);
2188 end if;
2189
2190 11 json := dumpJSONSCodeMod(classDef.modifications, scope, json);
2191 then
2192 ();
2193
2194 case SCode.ClassDef.CLASS_EXTENDS()
2195 algorithm
2196 ✗ json := dumpJSONSCodeMod(classDef.modifications, scope, json);
2197 then
2198 ();
2199
2200 else ();
2201 end match;
2202 end dumpJSONSCodeClassDef;
2203
2204 function dumpJSONChoicesAnnotation
2205 input list<SCode.SubMod> mods;
2206 input InstNode scope;
2207 input SourceInfo info;
2208 input Boolean failOnError;
2209 output JSON json = JSON.makeNull();
2210 protected
2211 SCode.SubMod smod;
2212 list<SCode.SubMod> choices, others;
2213 JSON j;
2214 algorithm
2215
7/8
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 1 time.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 1 time.
5 choices := list(m for m guard m.ident == "choice" in mods);
2216
7/8
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 1 time.
✓ Branch 7 taken 1 time.
✓ Branch 8 taken 1 time.
5 others := list(m for m guard m.ident <> "choice" in mods);
2217
2218
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if not listEmpty(choices) then
2219 1 j := JSON.emptyArray(listLength(choices));
2220
2221
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
4 for m in choices loop
2222 m := match m.mod
2223 case SCode.Mod.MOD(binding = NONE(), subModLst = {smod}) then smod;
2224 else m;
2225 end match;
2226
2227 3 j := JSON.addElement(dumpJSONSCodeMod_impl(m.mod, scope, isChoices = true), j);
2228 end for;
2229
2230 1 json := JSON.addPair("choice", j, json);
2231 end if;
2232
2233
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for m in others loop
2234 1 json := dumpJSONAnnotationSubMod(m, scope, failOnError, json);
2235 end for;
2236 end dumpJSONChoicesAnnotation;
2237
2238 public function modifierJSON
2239 input String modifier;
2240 output JSON json;
2241 protected
2242 Absyn.Modification amod;
2243 SCode.Mod smod;
2244 algorithm
2245 ✗ Absyn.ElementArg.MODIFICATION(modification = SOME(amod)) :=
2246 Parser.stringMod("dummy" + modifier);
2247 ✗ smod := AbsynToSCode.translateMod(SOME(amod),
2248 SCode.Final.NOT_FINAL(), SCode.Each.NOT_EACH(), NONE(), Absyn.dummyInfo);
2249 ✗ json := dumpJSONSCodeMod_impl(smod, InstNode.EMPTY_NODE());
2250 end modifierJSON;
2251
2252 annotation(__OpenModelica_Interface="nf_api");
2253 end NFInstanceAPI;
2254