Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 20
Functions: -% 0 / 1 / 1
Branches: -% 0 / 0 / 0

OMCompiler/Compiler/FFrontEnd/FMod.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 FMod
37 " file: FMod.mo
38 package: FMod
39 description: Utilities for Modifier handling
40
41
42 This module contains functions for modifier handling
43 "
44
45 // public imports
46 public
47 import Absyn;
48 import AbsynUtil;
49 import SCode;
50 import FCore;
51
52 // protected imports
53 protected
54 import List;
55 import Error;
56 import SCodeUtil;
57
58 public
59 type Name = FCore.Name;
60 type Id = FCore.Id;
61 type Seq = FCore.Seq;
62 type Next = FCore.Next;
63 type Node = FCore.Node;
64 type Data = FCore.Data;
65 type Kind = FCore.Kind;
66 type Ref = FCore.Ref;
67 type Refs = FCore.Refs;
68 type Children = FCore.Children;
69 type Parents = FCore.Parents;
70 type Scope = FCore.Scope;
71 type ImportTable = FCore.ImportTable;
72 type Graph = FCore.Graph;
73 type Extra = FCore.Extra;
74 type Visited = FCore.Visited;
75 type Import = FCore.Import;
76 type ModScope = FCore.ModScope;
77
78
79 public function merge
80 "@author: adrpo
81 merge 2 modifiers, one outer one inner"
82 input Ref inParentRef;
83 input Ref inOuterModRef;
84 input Ref inInnerModRef;
85 input Graph inGraph;
86 output Graph outGraph;
87 output Ref outMergedModRef;
88 algorithm
89 (outGraph, outMergedModRef) := match(inParentRef, inGraph)
90 local
91 Ref r;
92 Graph g;
93 case (r, g)
94 algorithm
95 then
96 (g, r);
97 end match;
98 end merge;
99
100 public function apply
101 "@author: adrpo
102 apply the modifier to the given target"
103 input Ref inTargetRef;
104 input Ref inModRef;
105 input Graph inGraph;
106 output Graph outGraph;
107 output Ref outNodeRef;
108 algorithm
109 (outGraph, outNodeRef) := match(inTargetRef, inGraph)
110 local
111 Ref r;
112 Graph g;
113 case (r, g)
114 algorithm
115 then
116 (g, r);
117 end match;
118 end apply;
119
120 public function compactSubMods
121 "This function merges the submodifiers in a modifier so that each submodifier
122 only occurs once. Ex:
123
124 compactMod({x.start = 2.0, y = 4.0, x(min = 1.0, max = 3.0)}) =>
125 {x(start = 2.0, min = 1.0, max = 3.0), y = 4.0}
126
127 "
128 input list<SCode.SubMod> inSubMods;
129 input ModScope inModScope;
130 output list<SCode.SubMod> outSubMods;
131 protected
132 list<SCode.SubMod> submods;
133 algorithm
134 ✗ submods := List.fold2(inSubMods, compactSubMod, inModScope, {}, {});
135 ✗ outSubMods := listReverse(submods);
136 end compactSubMods;
137
138 protected function compactSubMod
139 "Helper function to compactSubMods. Tries to merge the given modifier with an
140 existing modifier in the accumulation list. If a matching modifier is not
141 found in the list it's added instead."
142 input SCode.SubMod inSubMod;
143 input ModScope inModScope;
144 input list<String> inName;
145 input list<SCode.SubMod> inAccumMods;
146 output list<SCode.SubMod> outSubMods;
147 protected
148 String name;
149 list<SCode.SubMod> submods;
150 Boolean found;
151 algorithm
152 SCode.NAMEMOD(name, _) := inSubMod;
153 ✗ (submods, found) := List.findMap(inAccumMods,
154 function compactSubMod2(inNewMod = inSubMod, inModScope = inModScope, inName = inName));
155 ✗ outSubMods := List.consOnTrue(not found, inSubMod, submods);
156 end compactSubMod;
157
158 protected function compactSubMod2
159 "Helper function to compactSubMod. Merges the given modifier with the existing
160 modifier if they have the same name, otherwise does nothing."
161 input SCode.SubMod inExistingMod;
162 input SCode.SubMod inNewMod;
163 input ModScope inModScope;
164 input list<String> inName;
165 output SCode.SubMod outMod;
166 output Boolean outFound;
167 algorithm
168 (outMod, outFound) := match(inExistingMod, inNewMod)
169 local
170 String name1, name2;
171 SCode.SubMod submod;
172
173 case (SCode.NAMEMOD(ident = name1), SCode.NAMEMOD(ident = name2)) guard not stringEqual(name1, name2)
174 then
175 (inExistingMod, false);
176
177 case (SCode.NAMEMOD(ident = name1), _)
178 algorithm
179 ✗ submod := mergeSubModsInSameScope(inExistingMod, inNewMod, name1 :: inName, inModScope);
180 then
181 (submod, true);
182
183 end match;
184 end compactSubMod2;
185
186 protected function mergeSubModsInSameScope
187 "Merges two submodifiers in the same scope, i.e. they have the same priority.
188 It's thus an error if the modifiers modify the same element."
189 input SCode.SubMod inMod1;
190 input SCode.SubMod inMod2;
191 input list<String> inElementName;
192 input ModScope inModScope;
193 output SCode.SubMod outMod;
194 protected
195 String scope, name;
196 list<SCode.SubMod> submods;
197 SourceInfo info1, info2;
198 SCode.Mod mod1 = inMod1.mod, mod2 = inMod2.mod;
199 algorithm
200 outMod := match(mod1, mod2)
201 // The second modifier has no binding, use the binding from the first.
202 case (SCode.MOD(), SCode.MOD(binding = NONE()))
203 algorithm
204 ✗ submods := List.fold2(mod1.subModLst, compactSubMod, inModScope, inElementName, mod2.subModLst);
205 ✗ then
206 SCode.NAMEMOD(inMod1.ident, SCode.MOD(mod1.finalPrefix, mod1.eachPrefix,
207 submods, mod1.binding, mod1.comment, mod1.info));
208
209 // The first modifier has no binding, use the binding from the second.
210 case (SCode.MOD(binding = NONE()), SCode.MOD())
211 algorithm
212 ✗ submods := List.fold2(mod1.subModLst, compactSubMod, inModScope, inElementName, mod2.subModLst);
213 ✗ then
214 SCode.NAMEMOD(inMod2.ident, SCode.MOD(mod2.finalPrefix, mod2.eachPrefix,
215 submods, mod2.binding, mod2.comment, mod2.info));
216
217 // Both modifiers have a binding.
218 else
219 algorithm
220 ✗ info1 := SCodeUtil.getModifierInfo(mod1);
221 ✗ info2 := SCodeUtil.getModifierInfo(mod2);
222 ✗ scope := printModScope(inModScope);
223 ✗ name := stringDelimitList(listReverse(inElementName), ".");
224 ✗ Error.addMultiSourceMessage(Error.DUPLICATE_MODIFICATIONS,
225 {name, scope}, {info2, info1});
226 ✗ then
227 fail();
228
229 end match;
230 end mergeSubModsInSameScope;
231
232 protected function printModScope
233 input ModScope inModScope;
234 output String outString;
235 algorithm
236 outString := match inModScope
237 local
238 String name;
239 Absyn.Path path;
240
241 ✗ case FCore.MS_COMPONENT(name = name) then "component " + name;
242 ✗ case FCore.MS_EXTENDS(path = path) then "extends " + AbsynUtil.pathString(path);
243 ✗ case FCore.MS_DERIVED(path = path) then "inherited class " + AbsynUtil.pathString(path);
244 ✗ case FCore.MS_CLASS_EXTENDS(name = name) then "class extends class " + name;
245 ✗ case FCore.MS_CONSTRAINEDBY(path = path) then "constrainedby class " + AbsynUtil.pathString(path);
246
247 end match;
248 end printModScope;
249
250 annotation(__OpenModelica_Interface="frontend");
251 end FMod;
252