source: branches/dev-mj-5835/Compiler/ModelicaFlatTree/src/jastadd/FlatAPI/FlatAPI.jrag @ 13861

Last change on this file since 13861 was 13861, checked in by Jesper Mattsson, 6 weeks ago

Allowed format strings including the initial % (with a warning), and added unit tests of CFormatSpecifier. (#5835)

File size: 199.0 KB
Line 
1/*
2    Copyright (C) 2009 Modelon AB
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, version 3 of the License.
7
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12
13    You should have received a copy of the GNU General Public License
14    along with this program.  If not, see <http://www.gnu.org/licenses/>.
15*/
16
17import java.util.Collections;
18import java.util.LinkedHashSet;
19import java.util.HashSet;
20import java.util.Set;
21import java.util.ArrayList;
22import java.util.EnumMap;
23import java.io.File;
24import java.math.BigInteger;
25import java.io.PipedInputStream;
26import java.io.PipedOutputStream;
27import java.io.PrintStream;
28import java.io.FileInputStream;
29import java.io.IOException;
30import java.io.InputStream;
31import java.security.MessageDigest;
32import java.security.DigestOutputStream;
33import java.security.NoSuchAlgorithmException;
34
35import org.jmodelica.common.GUIDManager;
36import org.jmodelica.util.streams.StreamGobbler;
37import org.jmodelica.common.ast.prefixes.CausalityConnectorPrefix.CausalPortsEvaluator;
38
39aspect FlatAPI {
40
41    public class FClass {
42       
43        /**
44         * Enum like object which represents the most specific categorisation
45         * of a variable that is represented in our z-vector.
46         */
47        public static interface ZCategory {
48            public static final ZCategory TIME = 
49                    new FixedSizeCategory("TIME", "t", "time");
50            public static final ZCategory HOMOTOPY_LAMBDA = 
51                    new FixedSizeCategory("HOMOTOPY_LAMBDA", "homotopy_lambda", "_homotopy_lambda");
52           
53            public ZStructVector zStructVector();
54            public String zOffsetName();
55            public ZCategoryEntry createEntry(Collection<FVariable> vars, Enumerator enumerator, Integer offset);
56            public Comparator<FVariable> sorter(Collection<FVariable> vars, FClass fclass);
57            public int valueReferenceFromIndex(int index);
58            public void visitZOrder(ZVisitor v);
59        }
60       
61        /**
62         * A visitor for visiting each variable in Z order.
63         */
64        public static interface ZVisitor {
65            public void visitVariable(FVariable fv, ZCategoryEntry entry);
66            public void visitVirtualVariable(String name, String zOffsetName, int offset);
67        }
68
69        /**
70         * Implementation of ZCategory used by special constructs such as
71         * time and homotopy lambda.
72         */
73        public static class FixedSizeCategory implements ZCategory {
74            private final int size;
75            private final String name;
76            private final String zOffsetName;
77            private final String[] memberNames;
78
79            public FixedSizeCategory(String name, String zOffsetName, String... memberNames) {
80                this.size = memberNames.length;
81                this.name = name;
82                this.zOffsetName = zOffsetName;
83                this.memberNames = memberNames;
84            }
85
86            @Override
87            public ZStructVector zStructVector() {
88                return ZStructVector.DEFAULT;
89            }
90
91            @Override
92            public ZCategoryEntry createEntry(Collection<FVariable> vars, Enumerator enumerator, Integer groupOffset) {
93                if (vars.size() > 0) {
94                    throw new IllegalArgumentException("Special z index categories are not allowed to have entries!");
95                }
96                return new ZCategoryEntry(this, size, enumerator, groupOffset);
97            }
98
99            @Override
100            public Comparator<FVariable> sorter(Collection<FVariable> vars, FClass fclass) {
101                return null;
102            }
103
104            @Override
105            public String toString() {
106                return name;
107            }
108
109            @Override
110            public String zOffsetName() {
111                return zOffsetName;
112            }
113
114            @Override
115            public int valueReferenceFromIndex(int index) {
116                return index;
117            }
118
119            @Override
120            public void visitZOrder(ZVisitor v) {
121                for (int i = 0; i < size; i++) {
122                    v.visitVirtualVariable(memberNames[i], zOffsetName, i);
123                }
124            }
125
126        }
127
128        /**
129         * Used for specifying which z-vector is used for enumerating the
130         * specific variable category.
131         */
132        public static enum ZStructVector {
133            DEFAULT,
134            STRING,
135            EXTERNAL
136        }
137
138        /**
139         * Used in when specifying category for parameters (and constants).
140         * Parameters can be either independent or dependent. Dependent
141         * parameters are those which are calculated by a binding expression
142         * which references other parameters.
143         *
144         * Currently there is only independent constants.
145         */
146        public static enum ParaDependency {
147            INDEPENDENT ("i"),
148            DEPENDENT   ("d");
149
150            private final String zOffsetName;
151
152            private ParaDependency(String zOffsetName) {
153                this.zOffsetName = zOffsetName;
154            }
155
156            public String zOffsetName() {
157                return zOffsetName;
158            }
159        }
160
161        /**
162         * Enum like object which represents the different variable types we
163         * have in our z-vector.
164         *
165         * Can't be enum since we wan't to use generics. Makes list retrieval
166         * easier!
167         */
168        public static enum ZType {
169            REAL,
170            INTEGER   (1 << 28),
171            BOOLEAN   (2 << 28),
172            ENUM      (1 << 28, "integer"),
173            STRING    (3 << 28, ZStructVector.STRING),
174            EXTERNAL  (0, ZStructVector.EXTERNAL);
175
176            private final int valueReferenceMask;
177            private final ZStructVector zStructVector;
178            private final String zOffsetName;
179
180            private ZType() {
181                this(0);
182            }
183
184            private ZType(int valueReferenceMask) {
185                this(valueReferenceMask, ZStructVector.DEFAULT);
186            }
187
188            private ZType(int valueReferenceMask, String zOffsetName) {
189                this(valueReferenceMask, ZStructVector.DEFAULT, zOffsetName);
190            }
191
192            private ZType(int valueReferenceMask, ZStructVector zStructVector) {
193                this(valueReferenceMask, zStructVector, null);
194            }
195
196            private ZType(int valueReferenceMask, ZStructVector zStructVector, String zOffsetName) {
197                this.valueReferenceMask = valueReferenceMask;
198                this.zStructVector = zStructVector;
199                this.zOffsetName = (zOffsetName != null) ? zOffsetName : toString().toLowerCase();
200            }
201
202            public ZStructVector zStructVector() {
203                return zStructVector;
204            }
205
206            /**
207             * Takes a variable index and adds the types valuereference mask
208             */
209            public int mask(int index) {
210                return index ^ valueReferenceMask;
211            }
212
213            public String calcZOffsetName(ZVariability var, ParaDependency dependency) {
214                if (this == EXTERNAL) {
215                    return zOffsetName;
216                } else {
217                    return String.format(var.zOffsetNameFormat(), zOffsetName, dependency.zOffsetName());
218                }
219            }
220
221        }
222
223        /**
224         * Represents the different variabilities that are possible in the z-vector
225         */
226        public static enum ZVariability {
227            CONSTANT        ("c%s"),
228            REGULAR_PARAMETER,
229            STRUCTURAL_PARAMETER,
230            FINAL_PARAMETER,
231            EVAL_PARAMETER,
232            FREE_PARAMETER, // Only for Optimica!
233            INITIAL_PARAMETER,
234            DISCRETE        ("d"),
235            INPUT           ("u"),
236            DIFFERENTIATED  ("x"),
237            DERIVATIVE      ("dx"),
238            CONTINUOUS      ("w");
239
240            private final boolean isParameter;
241            private final String zOffsetNameFormat;
242
243            private ZVariability() {
244                this("p%s", true);
245            }
246
247            private ZVariability(String zOffsetName) {
248                this(zOffsetName, false);
249            }
250
251            private ZVariability(String zOffsetName, boolean isParameter) {
252                this.isParameter = isParameter;
253                this.zOffsetNameFormat = "%s_" + zOffsetName;
254            }
255
256            public boolean isParameter() {
257                return isParameter;
258            }
259
260            public String zOffsetNameFormat() {
261                return zOffsetNameFormat;
262            }
263        }
264
265        /**
266         * Class representing ordinary z-vector categories.
267         */
268        public static class ZOrdinaryCategory implements ZCategory {
269            private final static Map<Integer, ZOrdinaryCategory> lookupMap = new HashMap<Integer, ZOrdinaryCategory>();
270           
271            private static ZOrdinaryCategory create(ParaDependency dependency, ZType type, ZVariability variability) {
272                ZOrdinaryCategory category = new ZOrdinaryCategory(dependency, type, variability);
273                return category;
274            }
275
276            public static final ZOrdinaryCategory INDEPENDENT_REAL_CONSTANT                = create(ParaDependency.INDEPENDENT, ZType.REAL,    ZVariability.CONSTANT);
277            public static final ZOrdinaryCategory DEPENDENT_REAL_CONSTANT                  = create(ParaDependency.DEPENDENT,   ZType.REAL,    ZVariability.CONSTANT);
278            public static final ZOrdinaryCategory INDEPENDENT_REAL_REGULAR_PARAMETER       = create(ParaDependency.INDEPENDENT, ZType.REAL,    ZVariability.REGULAR_PARAMETER);
279            public static final ZOrdinaryCategory INDEPENDENT_REAL_STRUCTURAL_PARAMETER    = create(ParaDependency.INDEPENDENT, ZType.REAL,    ZVariability.STRUCTURAL_PARAMETER);
280            public static final ZOrdinaryCategory INDEPENDENT_REAL_FINAL_PARAMETER         = create(ParaDependency.INDEPENDENT, ZType.REAL,    ZVariability.FINAL_PARAMETER);
281            public static final ZOrdinaryCategory INDEPENDENT_REAL_EVAL_PARAMETER          = create(ParaDependency.INDEPENDENT, ZType.REAL,    ZVariability.EVAL_PARAMETER);
282            public static final ZOrdinaryCategory INDEPENDENT_REAL_FREE_PARAMETER          = create(ParaDependency.INDEPENDENT, ZType.REAL,    ZVariability.FREE_PARAMETER);
283            public static final ZOrdinaryCategory DEPENDENT_REAL_REGULAR_PARAMETER         = create(ParaDependency.DEPENDENT,   ZType.REAL,    ZVariability.REGULAR_PARAMETER);
284            public static final ZOrdinaryCategory DEPENDENT_REAL_STRUCTURAL_PARAMETER      = create(ParaDependency.DEPENDENT,   ZType.REAL,    ZVariability.STRUCTURAL_PARAMETER);
285            public static final ZOrdinaryCategory DEPENDENT_REAL_FINAL_PARAMETER           = create(ParaDependency.DEPENDENT,   ZType.REAL,    ZVariability.FINAL_PARAMETER);
286            public static final ZOrdinaryCategory DEPENDENT_REAL_EVAL_PARAMETER            = create(ParaDependency.DEPENDENT,   ZType.REAL,    ZVariability.EVAL_PARAMETER);
287            public static final ZOrdinaryCategory DEPENDENT_REAL_FREE_PARAMETER            = create(ParaDependency.DEPENDENT,   ZType.REAL,    ZVariability.FREE_PARAMETER);
288            public static final ZOrdinaryCategory REAL_INITIAL_PARAMETER                   = create(ParaDependency.DEPENDENT,   ZType.REAL,    ZVariability.INITIAL_PARAMETER);
289
290            public static final ZOrdinaryCategory INDEPENDENT_INTEGER_CONSTANT             = create(ParaDependency.INDEPENDENT, ZType.INTEGER, ZVariability.CONSTANT);
291            public static final ZOrdinaryCategory INDEPENDENT_ENUM_CONSTANT                = create(ParaDependency.INDEPENDENT, ZType.ENUM,    ZVariability.CONSTANT);
292            public static final ZOrdinaryCategory DEPENDENT_INTEGER_CONSTANT               = create(ParaDependency.DEPENDENT,   ZType.INTEGER, ZVariability.CONSTANT);
293            public static final ZOrdinaryCategory DEPENDENT_ENUM_CONSTANT                  = create(ParaDependency.DEPENDENT,   ZType.ENUM,    ZVariability.CONSTANT);
294            public static final ZOrdinaryCategory INDEPENDENT_INTEGER_REGULAR_PARAMETER    = create(ParaDependency.INDEPENDENT, ZType.INTEGER, ZVariability.REGULAR_PARAMETER);
295            public static final ZOrdinaryCategory INDEPENDENT_ENUM_REGULAR_PARAMETER       = create(ParaDependency.INDEPENDENT, ZType.ENUM,    ZVariability.REGULAR_PARAMETER);
296            public static final ZOrdinaryCategory INDEPENDENT_INTEGER_STRUCTURAL_PARAMETER = create(ParaDependency.INDEPENDENT, ZType.INTEGER, ZVariability.STRUCTURAL_PARAMETER);
297            public static final ZOrdinaryCategory INDEPENDENT_ENUM_STRUCTURAL_PARAMETER    = create(ParaDependency.INDEPENDENT, ZType.ENUM,    ZVariability.STRUCTURAL_PARAMETER);
298            public static final ZOrdinaryCategory INDEPENDENT_INTEGER_FINAL_PARAMETER      = create(ParaDependency.INDEPENDENT, ZType.INTEGER, ZVariability.FINAL_PARAMETER);
299            public static final ZOrdinaryCategory INDEPENDENT_ENUM_FINAL_PARAMETER         = create(ParaDependency.INDEPENDENT, ZType.ENUM,    ZVariability.FINAL_PARAMETER);
300            public static final ZOrdinaryCategory INDEPENDENT_INTEGER_EVAL_PARAMETER       = create(ParaDependency.INDEPENDENT, ZType.INTEGER, ZVariability.EVAL_PARAMETER);
301            public static final ZOrdinaryCategory INDEPENDENT_ENUM_EVAL_PARAMETER          = create(ParaDependency.INDEPENDENT, ZType.ENUM,    ZVariability.EVAL_PARAMETER);
302            public static final ZOrdinaryCategory INDEPENDENT_INTEGER_FREE_PARAMETER       = create(ParaDependency.INDEPENDENT, ZType.INTEGER, ZVariability.FREE_PARAMETER);
303            public static final ZOrdinaryCategory INDEPENDENT_ENUM_FREE_PARAMETER          = create(ParaDependency.INDEPENDENT, ZType.ENUM,    ZVariability.FREE_PARAMETER);
304            public static final ZOrdinaryCategory DEPENDENT_INTEGER_REGULAR_PARAMETER      = create(ParaDependency.DEPENDENT,   ZType.INTEGER, ZVariability.REGULAR_PARAMETER);
305            public static final ZOrdinaryCategory DEPENDENT_ENUM_REGULAR_PARAMETER         = create(ParaDependency.DEPENDENT,   ZType.ENUM,    ZVariability.REGULAR_PARAMETER);
306            public static final ZOrdinaryCategory DEPENDENT_INTEGER_STRUCTURAL_PARAMETER   = create(ParaDependency.DEPENDENT,   ZType.INTEGER, ZVariability.STRUCTURAL_PARAMETER);
307            public static final ZOrdinaryCategory DEPENDENT_ENUM_STRUCTURAL_PARAMETER      = create(ParaDependency.DEPENDENT,   ZType.ENUM,    ZVariability.STRUCTURAL_PARAMETER);
308            public static final ZOrdinaryCategory DEPENDENT_INTEGER_FINAL_PARAMETER        = create(ParaDependency.DEPENDENT,   ZType.INTEGER, ZVariability.FINAL_PARAMETER);
309            public static final ZOrdinaryCategory DEPENDENT_ENUM_FINAL_PARAMETER           = create(ParaDependency.DEPENDENT,   ZType.ENUM,    ZVariability.FINAL_PARAMETER);
310            public static final ZOrdinaryCategory DEPENDENT_INTEGER_EVAL_PARAMETER         = create(ParaDependency.DEPENDENT,   ZType.INTEGER, ZVariability.EVAL_PARAMETER);
311            public static final ZOrdinaryCategory DEPENDENT_ENUM_EVAL_PARAMETER            = create(ParaDependency.DEPENDENT,   ZType.ENUM,    ZVariability.EVAL_PARAMETER);
312            public static final ZOrdinaryCategory DEPENDENT_INTEGER_FREE_PARAMETER         = create(ParaDependency.DEPENDENT,   ZType.INTEGER, ZVariability.FREE_PARAMETER);
313            public static final ZOrdinaryCategory DEPENDENT_ENUM_FREE_PARAMETER            = create(ParaDependency.DEPENDENT,   ZType.ENUM,    ZVariability.FREE_PARAMETER);
314            public static final ZOrdinaryCategory INTEGER_INITIAL_PARAMETER                = create(ParaDependency.DEPENDENT,   ZType.INTEGER, ZVariability.INITIAL_PARAMETER);
315            public static final ZOrdinaryCategory ENUM_INITIAL_PARAMETER                   = create(ParaDependency.DEPENDENT,   ZType.ENUM,    ZVariability.INITIAL_PARAMETER);
316
317            public static final ZOrdinaryCategory INDEPENDENT_BOOLEAN_CONSTANT             = create(ParaDependency.INDEPENDENT, ZType.BOOLEAN, ZVariability.CONSTANT);
318            public static final ZOrdinaryCategory DEPENDENT_BOOLEAN_CONSTANT               = create(ParaDependency.DEPENDENT,   ZType.BOOLEAN, ZVariability.CONSTANT);
319            public static final ZOrdinaryCategory INDEPENDENT_BOOLEAN_REGULAR_PARAMETER    = create(ParaDependency.INDEPENDENT, ZType.BOOLEAN, ZVariability.REGULAR_PARAMETER);
320            public static final ZOrdinaryCategory INDEPENDENT_BOOLEAN_STRUCTURAL_PARAMETER = create(ParaDependency.INDEPENDENT, ZType.BOOLEAN, ZVariability.STRUCTURAL_PARAMETER);
321            public static final ZOrdinaryCategory INDEPENDENT_BOOLEAN_FINAL_PARAMETER      = create(ParaDependency.INDEPENDENT, ZType.BOOLEAN, ZVariability.FINAL_PARAMETER);
322            public static final ZOrdinaryCategory INDEPENDENT_BOOLEAN_EVAL_PARAMETER       = create(ParaDependency.INDEPENDENT, ZType.BOOLEAN, ZVariability.EVAL_PARAMETER);
323            public static final ZOrdinaryCategory INDEPENDENT_BOOLEAN_FREE_PARAMETER       = create(ParaDependency.INDEPENDENT, ZType.BOOLEAN, ZVariability.FREE_PARAMETER);
324            public static final ZOrdinaryCategory DEPENDENT_BOOLEAN_REGULAR_PARAMETER      = create(ParaDependency.DEPENDENT,   ZType.BOOLEAN, ZVariability.REGULAR_PARAMETER);
325            public static final ZOrdinaryCategory DEPENDENT_BOOLEAN_STRUCTURAL_PARAMETER   = create(ParaDependency.DEPENDENT,   ZType.BOOLEAN, ZVariability.STRUCTURAL_PARAMETER);
326            public static final ZOrdinaryCategory DEPENDENT_BOOLEAN_FINAL_PARAMETER        = create(ParaDependency.DEPENDENT,   ZType.BOOLEAN, ZVariability.FINAL_PARAMETER);
327            public static final ZOrdinaryCategory DEPENDENT_BOOLEAN_EVAL_PARAMETER         = create(ParaDependency.DEPENDENT,   ZType.BOOLEAN, ZVariability.EVAL_PARAMETER);
328            public static final ZOrdinaryCategory DEPENDENT_BOOLEAN_FREE_PARAMETER         = create(ParaDependency.DEPENDENT,   ZType.BOOLEAN, ZVariability.FREE_PARAMETER);
329            public static final ZOrdinaryCategory BOOLEAN_INITIAL_PARAMETER                = create(ParaDependency.DEPENDENT,   ZType.BOOLEAN, ZVariability.INITIAL_PARAMETER);
330
331            public static final ZOrdinaryCategory INDEPENDENT_STRING_CONSTANT              = create(ParaDependency.INDEPENDENT, ZType.STRING,  ZVariability.CONSTANT);
332            public static final ZOrdinaryCategory DEPENDENT_STRING_CONSTANT                = create(ParaDependency.DEPENDENT,   ZType.STRING,  ZVariability.CONSTANT);
333            public static final ZOrdinaryCategory INDEPENDENT_STRING_REGULAR_PARAMETER     = create(ParaDependency.INDEPENDENT, ZType.STRING,  ZVariability.REGULAR_PARAMETER);
334            public static final ZOrdinaryCategory INDEPENDENT_STRING_STRUCTURAL_PARAMETER  = create(ParaDependency.INDEPENDENT, ZType.STRING,  ZVariability.STRUCTURAL_PARAMETER);
335            public static final ZOrdinaryCategory INDEPENDENT_STRING_FINAL_PARAMETER       = create(ParaDependency.INDEPENDENT, ZType.STRING,  ZVariability.FINAL_PARAMETER);
336            public static final ZOrdinaryCategory INDEPENDENT_STRING_EVAL_PARAMETER        = create(ParaDependency.INDEPENDENT, ZType.STRING,  ZVariability.EVAL_PARAMETER);
337            public static final ZOrdinaryCategory DEPENDENT_STRING_REGULAR_PARAMETER       = create(ParaDependency.DEPENDENT,   ZType.STRING,  ZVariability.REGULAR_PARAMETER);
338            public static final ZOrdinaryCategory DEPENDENT_STRING_STRUCTURAL_PARAMETER    = create(ParaDependency.DEPENDENT,   ZType.STRING,  ZVariability.STRUCTURAL_PARAMETER);
339            public static final ZOrdinaryCategory DEPENDENT_STRING_FINAL_PARAMETER         = create(ParaDependency.DEPENDENT,   ZType.STRING,  ZVariability.FINAL_PARAMETER);
340            public static final ZOrdinaryCategory DEPENDENT_STRING_EVAL_PARAMETER          = create(ParaDependency.DEPENDENT,   ZType.STRING,  ZVariability.EVAL_PARAMETER);
341            public static final ZOrdinaryCategory STRING_INITIAL_PARAMETER                 = create(ParaDependency.DEPENDENT,   ZType.STRING,  ZVariability.INITIAL_PARAMETER);
342
343            public static final ZOrdinaryCategory INDEPENDENT_EXTERNAL_OBJECT              = create(ParaDependency.INDEPENDENT, ZType.EXTERNAL,ZVariability.REGULAR_PARAMETER);
344            public static final ZOrdinaryCategory DEPENDENT_EXTERNAL_OBJECT                = create(ParaDependency.DEPENDENT,   ZType.EXTERNAL,ZVariability.REGULAR_PARAMETER);
345            public static final ZOrdinaryCategory EXTERNAL_OBJECT_INITIAL_PARAMETER        = create(ParaDependency.DEPENDENT,   ZType.EXTERNAL,ZVariability.INITIAL_PARAMETER);
346
347            public static final ZOrdinaryCategory REAL_INPUT                               = create(ParaDependency.DEPENDENT,   ZType.REAL,    ZVariability.INPUT);
348            public static final ZOrdinaryCategory INTEGER_INPUT                            = create(ParaDependency.DEPENDENT,   ZType.INTEGER, ZVariability.INPUT);
349            public static final ZOrdinaryCategory ENUM_INPUT                               = create(ParaDependency.DEPENDENT,   ZType.ENUM,    ZVariability.INPUT);
350            public static final ZOrdinaryCategory BOOLEAN_INPUT                            = create(ParaDependency.DEPENDENT,   ZType.BOOLEAN, ZVariability.INPUT);
351            public static final ZOrdinaryCategory STRING_INPUT                             = create(ParaDependency.DEPENDENT,   ZType.STRING,  ZVariability.INPUT);
352
353            public static final ZOrdinaryCategory DISCRETE_REAL                            = create(ParaDependency.DEPENDENT,   ZType.REAL,    ZVariability.DISCRETE);
354            public static final ZOrdinaryCategory DISCRETE_INTEGER                         = create(ParaDependency.DEPENDENT,   ZType.INTEGER, ZVariability.DISCRETE);
355            public static final ZOrdinaryCategory DISCRETE_ENUM                            = create(ParaDependency.DEPENDENT,   ZType.ENUM,    ZVariability.DISCRETE);
356            public static final ZOrdinaryCategory DISCRETE_BOOLEAN                         = create(ParaDependency.DEPENDENT,   ZType.BOOLEAN, ZVariability.DISCRETE);
357            public static final ZOrdinaryCategory DISCRETE_STRING                          = create(ParaDependency.DEPENDENT,   ZType.STRING,  ZVariability.DISCRETE);
358
359            public static final ZOrdinaryCategory DIFFERENTIATED                           = new ZOrdinaryCategory(ParaDependency.DEPENDENT,   ZType.REAL,    ZVariability.DIFFERENTIATED) {
360                /**
361                 * This is needed since optimization and some simulation models
362                 * are extremely picky about the order of the states!
363                 */
364                @Override
365                public Comparator<FVariable> sorter(Collection<FVariable> vars, FClass fclass) {
366                    final Map<FVariable, Integer> posMap = new HashMap<FVariable, Integer>();
367                    int i = 0;
368                    for (FVariable var : fclass.differentiatedByFDerExp()) {
369                        posMap.put(var,  i++);
370                    }
371                    return new Comparator<FVariable>() {
372                        @Override
373                        public int compare(FVariable a, FVariable b) {
374                            Integer aPos = posMap.get(a);
375                            if (aPos == null) {
376                                throw new InternalCompilerError("Unable to determine index for differentiated variable " + a);
377                            }
378                            Integer bPos = posMap.get(b);
379                            if (bPos == null) {
380                                throw new InternalCompilerError("Unable to determine index for differentiated variable " + b);
381                            }
382                            return aPos - bPos;
383                        }};
384                };
385            };
386            public static final ZOrdinaryCategory DERIVATIVE                               = create(ParaDependency.DEPENDENT,   ZType.REAL,    ZVariability.DERIVATIVE);
387            public static final ZOrdinaryCategory CONTINUOUS                               = create(ParaDependency.DEPENDENT,   ZType.REAL,    ZVariability.CONTINUOUS);
388
389            public final ParaDependency dependency;
390            public final ZType type;
391            public final ZVariability variability;
392            private final String zOffsetName;
393
394            /**
395             * Use create method instead!
396             */
397            private ZOrdinaryCategory(ParaDependency dependency, ZType type, ZVariability variability) {
398                this.dependency = dependency;
399                this.type = type;
400                this.variability = variability;
401                this.zOffsetName = type.calcZOffsetName(variability, dependency);
402                lookupMap.put(computeLookupKey(this), this);
403            }
404
405            @Override
406            public ZStructVector zStructVector() {
407                return type.zStructVector();
408            }
409
410            @Override
411            public String zOffsetName() {
412                return zOffsetName;
413            }
414
415            @Override
416            public int valueReferenceFromIndex(int index) {
417                return type.mask(index);
418            }
419
420            @Override
421            public void visitZOrder(ZVisitor v) {}
422
423            @Override
424            public ZCategoryEntry createEntry(Collection<FVariable> vars, Enumerator enumerator, Integer groupOffset) {
425                return new ZCategoryEntry(this, vars, enumerator, groupOffset);
426            }
427
428            private static int computeLookupKey(ZOrdinaryCategory category) {
429                return computeLookupKey(category.dependency, category.type, category.variability);
430            }
431
432            private static int computeLookupKey(ParaDependency dependency, ZType type, ZVariability variability) {
433                return dependency.hashCode() ^ type.hashCode() ^ variability.hashCode();
434            }
435
436            public static ZOrdinaryCategory resolve(FVariable var) {
437                if (var == null || var.isPreVariable()) {
438                    // Pre variables should be excluded!
439                    return null;
440                }
441                ParaDependency dependency;
442                if (var.isIndependentConstant() || var.isIndependentParameter()) {
443                    dependency = ParaDependency.INDEPENDENT;
444                } else {
445                    dependency = ParaDependency.DEPENDENT;
446                }
447                ZType type = var.type().genType();
448                ZVariability variability = var.zVariability();
449                // If any of these are null, then this variable is not of
450                // interest and should be ignored, indicate this with null.
451                if (dependency == null || type == null || variability == null) {
452                    return null;
453                }
454                return lookupMap.get(computeLookupKey(dependency, type, variability));
455            }
456
457            @Override
458            public Comparator<FVariable> sorter(Collection<FVariable> vars, FClass fclass) {
459                return null;
460            }
461
462            @Override
463            public String toString() {
464                return dependency + "_" + type + "_" + variability;
465            }
466        }
467
468        /**
469         * Manages value references for variables
470         */
471        public static class VarRefMap {
472            private static final ZCategory[] zIndexOrder = new ZCategory[] {
473                    ZOrdinaryCategory.INDEPENDENT_REAL_CONSTANT,
474                    ZOrdinaryCategory.DEPENDENT_REAL_CONSTANT,
475                    ZOrdinaryCategory.INDEPENDENT_REAL_REGULAR_PARAMETER,
476                    ZOrdinaryCategory.INDEPENDENT_REAL_STRUCTURAL_PARAMETER,
477                    ZOrdinaryCategory.INDEPENDENT_REAL_FINAL_PARAMETER,
478                    ZOrdinaryCategory.INDEPENDENT_REAL_EVAL_PARAMETER,
479                    ZOrdinaryCategory.INDEPENDENT_REAL_FREE_PARAMETER,
480                    ZOrdinaryCategory.DEPENDENT_REAL_REGULAR_PARAMETER,
481                    ZOrdinaryCategory.DEPENDENT_REAL_STRUCTURAL_PARAMETER,
482                    ZOrdinaryCategory.DEPENDENT_REAL_FINAL_PARAMETER,
483                    ZOrdinaryCategory.DEPENDENT_REAL_EVAL_PARAMETER,
484                    ZOrdinaryCategory.DEPENDENT_REAL_FREE_PARAMETER,
485                    ZOrdinaryCategory.REAL_INITIAL_PARAMETER,
486
487                    ZOrdinaryCategory.INDEPENDENT_INTEGER_CONSTANT,
488                    ZOrdinaryCategory.INDEPENDENT_ENUM_CONSTANT,
489                    ZOrdinaryCategory.DEPENDENT_INTEGER_CONSTANT,
490                    ZOrdinaryCategory.DEPENDENT_ENUM_CONSTANT,
491                    ZOrdinaryCategory.INDEPENDENT_INTEGER_REGULAR_PARAMETER,
492                    ZOrdinaryCategory.INDEPENDENT_ENUM_REGULAR_PARAMETER,
493                    ZOrdinaryCategory.INDEPENDENT_INTEGER_STRUCTURAL_PARAMETER,
494                    ZOrdinaryCategory.INDEPENDENT_ENUM_STRUCTURAL_PARAMETER,
495                    ZOrdinaryCategory.INDEPENDENT_INTEGER_FINAL_PARAMETER,
496                    ZOrdinaryCategory.INDEPENDENT_ENUM_FINAL_PARAMETER,
497                    ZOrdinaryCategory.INDEPENDENT_INTEGER_EVAL_PARAMETER,
498                    ZOrdinaryCategory.INDEPENDENT_ENUM_EVAL_PARAMETER,
499                    ZOrdinaryCategory.INDEPENDENT_INTEGER_FREE_PARAMETER,
500                    ZOrdinaryCategory.INDEPENDENT_ENUM_FREE_PARAMETER,
501                    ZOrdinaryCategory.DEPENDENT_INTEGER_REGULAR_PARAMETER,
502                    ZOrdinaryCategory.DEPENDENT_ENUM_REGULAR_PARAMETER,
503                    ZOrdinaryCategory.DEPENDENT_INTEGER_STRUCTURAL_PARAMETER,
504                    ZOrdinaryCategory.DEPENDENT_ENUM_STRUCTURAL_PARAMETER,
505                    ZOrdinaryCategory.DEPENDENT_INTEGER_FINAL_PARAMETER,
506                    ZOrdinaryCategory.DEPENDENT_ENUM_FINAL_PARAMETER,
507                    ZOrdinaryCategory.DEPENDENT_INTEGER_EVAL_PARAMETER,
508                    ZOrdinaryCategory.DEPENDENT_ENUM_EVAL_PARAMETER,
509                    ZOrdinaryCategory.DEPENDENT_INTEGER_FREE_PARAMETER,
510                    ZOrdinaryCategory.DEPENDENT_ENUM_FREE_PARAMETER,
511                    ZOrdinaryCategory.INTEGER_INITIAL_PARAMETER,
512                    ZOrdinaryCategory.ENUM_INITIAL_PARAMETER,
513
514                    ZOrdinaryCategory.INDEPENDENT_BOOLEAN_CONSTANT,
515                    ZOrdinaryCategory.DEPENDENT_BOOLEAN_CONSTANT,
516                    ZOrdinaryCategory.INDEPENDENT_BOOLEAN_REGULAR_PARAMETER,
517                    ZOrdinaryCategory.INDEPENDENT_BOOLEAN_STRUCTURAL_PARAMETER,
518                    ZOrdinaryCategory.INDEPENDENT_BOOLEAN_FINAL_PARAMETER,
519                    ZOrdinaryCategory.INDEPENDENT_BOOLEAN_EVAL_PARAMETER,
520                    ZOrdinaryCategory.INDEPENDENT_BOOLEAN_FREE_PARAMETER,
521                    ZOrdinaryCategory.DEPENDENT_BOOLEAN_REGULAR_PARAMETER,
522                    ZOrdinaryCategory.DEPENDENT_BOOLEAN_STRUCTURAL_PARAMETER,
523                    ZOrdinaryCategory.DEPENDENT_BOOLEAN_FINAL_PARAMETER,
524                    ZOrdinaryCategory.DEPENDENT_BOOLEAN_EVAL_PARAMETER,
525                    ZOrdinaryCategory.DEPENDENT_BOOLEAN_FREE_PARAMETER,
526                    ZOrdinaryCategory.BOOLEAN_INITIAL_PARAMETER,
527
528                    ZOrdinaryCategory.DERIVATIVE,
529                    ZOrdinaryCategory.DIFFERENTIATED,
530                    ZOrdinaryCategory.REAL_INPUT,
531                    ZOrdinaryCategory.CONTINUOUS,
532
533                    ZCategory.TIME,
534                    ZCategory.HOMOTOPY_LAMBDA,
535
536                    ZOrdinaryCategory.DISCRETE_REAL,
537
538                    ZOrdinaryCategory.DISCRETE_INTEGER,
539                    ZOrdinaryCategory.DISCRETE_ENUM,
540
541                    ZOrdinaryCategory.INTEGER_INPUT,
542                    ZOrdinaryCategory.ENUM_INPUT,
543
544                    ZOrdinaryCategory.DISCRETE_BOOLEAN,
545                    ZOrdinaryCategory.BOOLEAN_INPUT,
546
547                    ZOrdinaryCategory.INDEPENDENT_STRING_CONSTANT,
548                    ZOrdinaryCategory.DEPENDENT_STRING_CONSTANT,
549                    ZOrdinaryCategory.INDEPENDENT_STRING_REGULAR_PARAMETER,
550                    ZOrdinaryCategory.INDEPENDENT_STRING_STRUCTURAL_PARAMETER,
551                    ZOrdinaryCategory.INDEPENDENT_STRING_FINAL_PARAMETER,
552                    ZOrdinaryCategory.INDEPENDENT_STRING_EVAL_PARAMETER,
553                    ZOrdinaryCategory.DEPENDENT_STRING_REGULAR_PARAMETER,
554                    ZOrdinaryCategory.DEPENDENT_STRING_STRUCTURAL_PARAMETER,
555                    ZOrdinaryCategory.DEPENDENT_STRING_FINAL_PARAMETER,
556                    ZOrdinaryCategory.DEPENDENT_STRING_EVAL_PARAMETER,
557                    ZOrdinaryCategory.STRING_INITIAL_PARAMETER,
558
559                    ZOrdinaryCategory.DISCRETE_STRING,
560                    ZOrdinaryCategory.STRING_INPUT,
561
562                    ZOrdinaryCategory.INDEPENDENT_EXTERNAL_OBJECT,
563                    ZOrdinaryCategory.DEPENDENT_EXTERNAL_OBJECT,
564                    ZOrdinaryCategory.EXTERNAL_OBJECT_INITIAL_PARAMETER,
565            };
566
567            private static final ZCategory[] zIndexOrderPre = new ZCategory[] {
568                    ZOrdinaryCategory.DERIVATIVE,
569                    ZOrdinaryCategory.DIFFERENTIATED,
570                    ZOrdinaryCategory.REAL_INPUT,
571                    ZOrdinaryCategory.CONTINUOUS,
572
573                    ZOrdinaryCategory.DISCRETE_REAL,
574
575                    ZOrdinaryCategory.DISCRETE_INTEGER,
576                    ZOrdinaryCategory.DISCRETE_ENUM,
577
578                    ZOrdinaryCategory.INTEGER_INPUT,
579                    ZOrdinaryCategory.ENUM_INPUT,
580
581                    ZOrdinaryCategory.DISCRETE_BOOLEAN,
582                    ZOrdinaryCategory.BOOLEAN_INPUT,
583                   
584                    ZOrdinaryCategory.DISCRETE_STRING,
585                    ZOrdinaryCategory.STRING_INPUT,
586            };
587
588            private final Map<ZCategory, ZCategoryEntry> categoryMap;
589
590            public VarRefMap(Iterable<FVariable> vars, FClass fclass) {
591                Map<ZCategory, java.util.List<FVariable>> varMap = new HashMap<>(zIndexOrder.length);
592                Map<String, Integer> zOffsetMap = new HashMap<>(zIndexOrder.length);
593                Map<ZStructVector, Enumerator> vectorEnumerators = new HashMap<>(zIndexOrder.length);
594                for (ZCategory category : zIndexOrder) {
595                    if (varMap.put(category, new ArrayList<FVariable>()) != null) {
596                        throw new IllegalArgumentException("There are multiple entries for " + category + " in z index map");
597                    }
598                    ZStructVector zStructVector = category.zStructVector();
599                    if (!vectorEnumerators.containsKey(zStructVector)) {
600                        vectorEnumerators.put(zStructVector, new Enumerator());
601                    }
602                }
603                for (FVariable var : vars) {
604                    ZCategory category = var.zCategory();
605                    if (category == null) {
606                        // Ignore, not supposed to be in any index map!
607                        continue;
608                    }
609                    Collection<FVariable> catVars = varMap.get(category);
610                    if (catVars == null) {
611                        // Ignore, not of interest in this index map!
612                        continue;
613                    }
614                    catVars.add(var);
615                }
616                categoryMap = new LinkedHashMap<ZCategory, ZCategoryEntry>(zIndexOrder.length);
617                String prevZOffsetName = null;
618                for (ZCategory category : zIndexOrder) {
619                    java.util.List<FVariable> categoryVars = varMap.get(category);
620                    Comparator<FVariable> sorter = category.sorter(categoryVars, fclass);
621                    if (sorter != null) {
622                        Collections.sort(categoryVars, sorter);
623                    }
624                    Enumerator enumerator = vectorEnumerators.get(category.zStructVector());
625                    String zOffsetName = category.zOffsetName();
626                    ZCategoryEntry entry = category.createEntry(
627                            categoryVars, enumerator, zOffsetMap.get(zOffsetName));
628                    categoryMap.put(category, entry);
629                    if (!zOffsetMap.containsKey(zOffsetName)) {
630                        zOffsetMap.put(zOffsetName, entry.offset());
631                    } else if (!zOffsetName.equals(prevZOffsetName)) {
632                        throw new IllegalArgumentException(
633                                "Z offset category '" + zOffsetName + "' is not continuous in z index map.");
634                    }
635                    prevZOffsetName = zOffsetName;
636                }
637            }
638
639            /**
640             * Used for filtering on specific categories
641             */
642            public static abstract class CategoryFilter implements Criteria<Map.Entry<ZCategory, ZCategoryEntry>> {
643                @Override
644                public boolean test(Entry<ZCategory, ZCategoryEntry> elem) {
645                    if (elem.getKey() instanceof ZOrdinaryCategory) {
646                        return test((ZOrdinaryCategory) elem.getKey());
647                    } else {
648                        return false;
649                    }
650                }
651
652                /**
653                 * Null safe version of test(ZOrdinaryCategory). E.g. if null
654                 * is given, then false is returned.
655                 */
656                public boolean testSingle(ZOrdinaryCategory category) {
657                    return category != null && test(category);
658                }
659
660                protected abstract boolean test(ZOrdinaryCategory category);
661            }
662
663            /**
664             * Provides a collection containing all variables with specified
665             * type. This collection is read only and only support a small
666             * number of operations that collection supports.
667             */
668            public Collection<FVariable> getBy(final ZType type) {
669                return getBy(new CategoryFilter() {
670                    @Override
671                    protected boolean test(ZOrdinaryCategory category) {
672                        return category.type == type;
673                    }
674                });
675            }
676
677            /**
678             * Provides a collection containing all variables with specified
679             * variability. This collection is read only and only support a
680             * small number of operations that collection supports.
681             */
682            public Collection<FVariable> getBy(final ZVariability variability) {
683                return getBy(new CategoryFilter() {
684                    @Override
685                    protected boolean test(ZOrdinaryCategory category) {
686                        return category.variability == variability;
687                    }
688                   
689                });
690            }
691
692            /**
693             * Provides a collection containing all variables with specified
694             * dependency and variability. This collection is read only and
695             * only support a small number of operations that collection supports.
696             */
697            public Collection<FVariable> getBy(final ParaDependency dependency, final ZVariability variability) {
698                return getBy(new CategoryFilter() {
699                    @Override
700                    protected boolean test(ZOrdinaryCategory category) {
701                        return category.dependency == dependency && category.variability == variability;
702                    }
703                   
704                });
705            }
706
707            private static final CategoryFilter PARAMETER_FILTER = new CategoryFilter() {
708                @Override
709                public boolean test(ZOrdinaryCategory category) {
710                    return category.variability.isParameter();
711                }
712               
713            };
714
715            /**
716             * Provides a collection containing all parameters with specified
717             * dependency. This collection is read only and only support a
718             * small number of operations that collection supports.
719             */
720            public Collection<FVariable> getParameterBy(final ParaDependency dependency) {
721                return getBy(new CategoryFilter() {
722                    @Override
723                    protected boolean test(ZOrdinaryCategory category) {
724                        return category.dependency == dependency && PARAMETER_FILTER.test(category);
725                    }
726                   
727                });
728            }
729
730            /**
731             * Provides a collection containing all parameters with specified
732             * dependency and type. This collection is read only and only
733             * support a small number of operations that collection supports.
734             */
735            public Collection<FVariable> getParameterBy(final ParaDependency dependency, final ZType type) {
736                return getBy(new CategoryFilter() {
737                    @Override
738                    protected boolean test(ZOrdinaryCategory category) {
739                        return category.dependency == dependency && category.type == type && PARAMETER_FILTER.test(category);
740                    }
741                   
742                });
743            }
744
745            public Collection<FVariable> getBy(CategoryFilter filter) {
746                return new SelectiveCollection(filter);
747            }
748
749            public ZCategoryEntry getBy(ZCategory category) {
750                return categoryMap.get(category);
751            }
752
753            /**
754             * Visit all variables in z-order, using provided visitor.
755             * If pre is true, then visit only those categories that have pre versions.
756             */
757            public void visitZOrder(ZVisitor v, boolean pre) {
758                for (ZCategory category : (pre ? zIndexOrderPre : zIndexOrder)) {
759                    getBy(category).visitZOrder(v);
760                }
761            }
762
763            @Override
764            public String toString() {
765                StringBuilder sb = new StringBuilder();
766                for (Map.Entry<ZCategory, ZCategoryEntry> entry : categoryMap.entrySet()) {
767                    if (entry.getValue().size > 0) {
768                        sb.append(entry.getKey());
769                        sb.append(" (");
770                        sb.append(entry.getValue().size);
771                        sb.append(" scalars, ");
772                        sb.append(entry.getValue().indexMap.size());
773                        sb.append(" entries):\n");
774                        for (Map.Entry<FVariable, Integer> varEntry : entry.getValue().indexMap.entrySet()) {
775                            sb.append("  ");
776                            sb.append(varEntry.getValue());
777                            sb.append(": ");
778                            sb.append(varEntry.getKey().name());
779                            sb.append("\n");
780                        }
781                    }
782                }
783                return sb.toString();
784            }
785
786            /**
787             * Class which is returned when selecting a sub-set of the
788             * categories.
789             */
790            private class SelectiveCollection implements Collection<FVariable> {
791                private final Iterable<Map.Entry<ZCategory, ZCategoryEntry>> entries;
792
793                private SelectiveCollection(CategoryFilter filter) {
794                    entries = new FilteredIterable<Map.Entry<ZCategory, ZCategoryEntry>>(categoryMap.entrySet(), filter);
795                }
796
797                public int size() {
798                    int size = 0;
799                    for (Map.Entry<ZCategory, ZCategoryEntry> entry : entries) {
800                        size += entry.getValue().size;
801                    }
802                    return size;
803                }
804
805                @Override
806                public Iterator<FVariable> iterator() {
807                    return new Iterator<FVariable>() {
808
809                        private Iterator<FVariable> current;
810                        private Iterator<Map.Entry<ZCategory, ZCategoryEntry>> entryIter = entries.iterator();
811
812                        @Override
813                        public boolean hasNext() {
814                            while ((current == null || !current.hasNext()) && entryIter.hasNext()) {
815                                current = entryIter.next().getValue().iterator();
816                            }
817                            return current.hasNext();
818                        }
819
820                        @Override
821                        public FVariable next() {
822                            if (!hasNext()) {
823                                throw new NoSuchElementException();
824                            }
825                            return current.next();
826                        }
827
828                        @Override
829                        public void remove() {
830                            throw new UnsupportedOperationException();
831                        }
832                    };
833                }
834
835                @Override
836                public boolean add(FVariable arg0) {
837                    throw new UnsupportedOperationException();
838                }
839
840                @Override
841                public boolean addAll(Collection<? extends FVariable> c) {
842                    throw new UnsupportedOperationException();
843                }
844
845                @Override
846                public void clear() {
847                    throw new UnsupportedOperationException();
848                }
849
850                @Override
851                public boolean contains(Object o) {
852                    throw new UnsupportedOperationException("Don't use, inefficient!");
853                }
854
855                @Override
856                public boolean containsAll(Collection<?> c) {
857                    throw new UnsupportedOperationException("Don't use, inefficient!");
858                }
859
860                @Override
861                public boolean isEmpty() {
862                    return size() == 0;
863                }
864
865                @Override
866                public boolean remove(Object o) {
867                    throw new UnsupportedOperationException();
868                }
869
870                @Override
871                public boolean removeAll(Collection<?> c) {
872                    throw new UnsupportedOperationException();
873                }
874
875                @Override
876                public boolean retainAll(Collection<?> c) {
877                    throw new UnsupportedOperationException();
878                }
879
880                @Override
881                public Object[] toArray() {
882                    throw new UnsupportedOperationException();
883                }
884
885                @Override
886                public <T> T[] toArray(T[] a) {
887                    throw new UnsupportedOperationException();
888                }
889            }
890        }
891
892        /**
893         * Represents an entry of ZCategory and contains the offset, size and
894         * variables which falls into the specified category.
895         *
896         * This class only implements a sub-set of the collection interface.
897         */
898        public static class ZCategoryEntry implements Collection<FVariable> {
899            private final int offset;
900            private final int groupOffset;
901            private final int size;
902            private final Map<FVariable, Integer> indexMap;
903            private final ZCategory category;
904
905            public ZCategoryEntry(ZCategory category, int size, Enumerator enumerator, Integer groupOffset) {
906                this.category = category;
907                this.offset = enumerator.peek();
908                this.groupOffset = (groupOffset == null) ? this.offset : groupOffset;
909                this.size = size;
910                this.indexMap = Collections.emptyMap();
911                // Now wind forward the enumerator
912                for (int i = 0; i < size; i++, enumerator.next());
913            }
914
915            public ZCategoryEntry(ZCategory category, Collection<FVariable> vars, Enumerator enumerator, Integer groupOffset) {
916                this.category = category;
917                this.offset = enumerator.peek();
918                this.groupOffset = (groupOffset == null) ? this.offset : groupOffset;
919                Map<FVariable, Integer> indexMap = new LinkedHashMap<FVariable, Integer>(vars.size());
920                for (FVariable var : vars) {
921                    indexMap.put(var, var.incrementValueReferenceIndex(enumerator));
922                }
923                size = enumerator.peek() - this.offset;
924                this.indexMap = Collections.unmodifiableMap(indexMap);
925            }
926
927            public int getIndexFor(FVariable var) {
928                return indexMap.get(var);
929            }
930
931            public int getOffsetIndexFor(FVariable var) {
932                return indexMap.get(var) - groupOffset;
933            }
934
935            public int getValueReferenceFor(FVariable var) {
936                return category.valueReferenceFromIndex(getIndexFor(var));
937            }
938
939            public int offset() {
940                return offset;
941            }
942
943            public ZCategory category() {
944                return category;
945            }
946
947            public void visitZOrder(ZVisitor v) {
948                category.visitZOrder(v);
949                for (FVariable fv : this) {
950                    v.visitVariable(fv, this);
951                }
952            }
953
954            @Override
955            public Iterator<FVariable> iterator() {
956                return indexMap.keySet().iterator();
957            }
958
959            @Override
960            public boolean add(FVariable e) {
961                throw new UnsupportedOperationException();
962            }
963
964            @Override
965            public boolean addAll(Collection<? extends FVariable> c) {
966                throw new UnsupportedOperationException();
967            }
968
969            @Override
970            public void clear() {
971                throw new UnsupportedOperationException();
972            }
973
974            @Override
975            public boolean contains(Object o) {
976                throw new UnsupportedOperationException("Don't use, inefficient!");
977            }
978
979            @Override
980            public boolean containsAll(Collection<?> c) {
981                throw new UnsupportedOperationException("Don't use, inefficient!");
982            }
983
984            @Override
985            public boolean isEmpty() {
986                return size() == 0;
987            }
988
989            @Override
990            public boolean remove(Object o) {
991                throw new UnsupportedOperationException();
992            }
993
994            @Override
995            public boolean removeAll(Collection<?> c) {
996                throw new UnsupportedOperationException();
997            }
998
999            @Override
1000            public boolean retainAll(Collection<?> c) {
1001                throw new UnsupportedOperationException();
1002            }
1003
1004            @Override
1005            public int size() {
1006                return size;
1007            }
1008
1009            @Override
1010            public Object[] toArray() {
1011                throw new UnsupportedOperationException();
1012            }
1013
1014            @Override
1015            public <T> T[] toArray(T[] a) {
1016                throw new UnsupportedOperationException();
1017            }
1018        }
1019    }
1020
1021    /**
1022     * Returns the z variability enum for this variability and supplied
1023     * variable.
1024     */
1025    public FClass.ZVariability TypePrefixVariability.zVariability(FVariable var) {
1026        return null;
1027    }
1028    public FClass.ZVariability Constant.zVariability(FVariable var) {
1029        return FClass.ZVariability.CONSTANT;
1030    }
1031    public FClass.ZVariability FixedParameter.zVariability(FVariable var) {
1032        return FClass.ZVariability.REGULAR_PARAMETER;
1033    }
1034    public FClass.ZVariability StructParameter.zVariability(FVariable var) {
1035        return FClass.ZVariability.STRUCTURAL_PARAMETER;
1036    }
1037    public FClass.ZVariability FinalParameter.zVariability(FVariable var) {
1038        return FClass.ZVariability.FINAL_PARAMETER;
1039    }
1040    public FClass.ZVariability EvalTrueParameter.zVariability(FVariable var) {
1041        return FClass.ZVariability.EVAL_PARAMETER;
1042    }
1043    public FClass.ZVariability InitialParameter.zVariability(FVariable var) {
1044        return FClass.ZVariability.INITIAL_PARAMETER;
1045    }
1046    public FClass.ZVariability Discrete.zVariability(FVariable var) {
1047        if (var.isInput()) {
1048            return FClass.ZVariability.INPUT;
1049        } else {
1050            return FClass.ZVariability.DISCRETE;
1051        }
1052    }
1053    public FClass.ZVariability Continuous.zVariability(FVariable var) {
1054        if (var.isInput()) {
1055            return FClass.ZVariability.INPUT;
1056        } else if (var.differentiatedByFDerExp()) {
1057            return FClass.ZVariability.DIFFERENTIATED;
1058        } else if (var.isDerivativeVariable()) {
1059            return FClass.ZVariability.DERIVATIVE;
1060        } else {
1061            return FClass.ZVariability.CONTINUOUS;
1062        }
1063    }
1064
1065    /**
1066     * Util for finding all differentiated variables. Can't use the fact that
1067     * for var x there is a variable der(x), not true before additon of
1068     * derivative variables!
1069     */
1070    coll LinkedHashSet<FVariable> FClass.differentiatedByFDerExp() 
1071        [new LinkedHashSet<FVariable>()] with add root FClass;
1072    FDerExp contributes getFAccess().myFV().asFVariable() when getFAccess().myFV().isFVariable() && !inDeadIfBranch()
1073        to FClass.differentiatedByFDerExp() for myFClass();
1074    FDerivativeVariable contributes myDifferentiatedVariable().asFVariable() when (shouldContribute())
1075        to FClass.differentiatedByFDerExp() for myFClass();
1076
1077    syn boolean FVariable.differentiatedByFDerExp() = myFClass().differentiatedByFDerExp().contains(this);
1078
1079    /**
1080     * Calculates the z variability enum for this variable.
1081     */
1082    syn FClass.ZVariability FVariable.zVariability() = getTypePrefixVariability().zVariability(this);
1083
1084    syn FClass.ZType FType.genType() = null;
1085    eq FBooleanType.genType()          = FClass.ZType.BOOLEAN;
1086    eq FEnumLiteralType.genType()      = FClass.ZType.ENUM;
1087    eq FEnumType.genType()             = FClass.ZType.ENUM;
1088    eq FIntegerType.genType()          = FClass.ZType.INTEGER;
1089    eq FRealType.genType()             = FClass.ZType.REAL;
1090    eq FStringType.genType()           = FClass.ZType.STRING;
1091    eq FExternalObjectType.genType()   = FClass.ZType.EXTERNAL;
1092
1093    /**
1094     * Lazy attribute which holds the variable reference map.
1095     */
1096    syn lazy VarRefMap FClass.varRefMap() = new VarRefMap(getFVariables(), this);
1097
1098    syn FClass.ZOrdinaryCategory FVariable.zCategory() = FClass.ZOrdinaryCategory.resolve(this);
1099
1100    public int FVariable.incrementValueReferenceIndex(Enumerator e) {
1101        return e.next();
1102    }
1103
1104    /**
1105     * The value reference value is represented by a 32 bit unsigned integer
1106     * variable. The lowest 27 bits is used to represent the index of a
1107     * variable of the corresponding variable vector. Real, Integer, Boolean and
1108     * enumeration variables share a vector, while String variables has their
1109     * own vector.
1110     * Bit 28 is reserved for representing negated/not negated.
1111     * Bits 29-31 represents the primitive type, where:
1112     * 0: Real
1113     * 1: Integer or enumeration
1114     * 2: Boolean
1115     * 3: String
1116     * Bit 32 is left unused.
1117     *
1118     */
1119    inh lazy int FAbstractVariable.valueReference();
1120    eq FClass.getFVariable(int i).valueReference() {
1121        FVariable var = getFVariable(i);
1122        ZOrdinaryCategory category = ZOrdinaryCategory.resolve(var);
1123        if (category == null) {
1124            return -1;
1125        }
1126        return category.type.mask(varRefMap().getBy(category).getIndexFor(var));
1127    }
1128    eq FClass.getAliasVariable(int i).valueReference() = getAliasVariable(i).aliasValueReference();
1129    eq FClass.getFAbstractEquation().valueReference()  = -1;
1130    eq Root.getChild().valueReference()                = -1;
1131   
1132    syn int FVariable.aliasValueReference() = alias() != null ? alias().valueReference() : -1;
1133
1134    syn int FAbstractVariable.indexInZ() = -1;
1135    eq FVariable.indexInZ() = valueReference() & 0x07FFFFFF;
1136
1137    syn boolean FAccessExp.isConsecutiveInZ(FAccessExp use) = myFV().isConsecutiveInZ(use.myFV());
1138
1139    syn boolean FAbstractVariable.isConsecutiveInZ(FAbstractVariable fv) = false;
1140    eq FVariable.isConsecutiveInZ(FAbstractVariable fv) = indexInZ() + 1 == fv.indexInZ();
1141
1142   
1143    syn int FClass.derivativeVariablesOffset() = varRefMap().getBy(ZOrdinaryCategory.DERIVATIVE).offset();
1144    syn int FClass.realInputsOffset() = varRefMap().getBy(ZOrdinaryCategory.REAL_INPUT).offset();
1145    syn int FClass.algebraicContinousRealVariablesOffset() = varRefMap().getBy(ZOrdinaryCategory.CONTINUOUS).offset();
1146
1147
1148    syn int FClass.integerInputsOffset() = varRefMap().getBy(ZOrdinaryCategory.INTEGER_INPUT).offset();
1149    syn int FClass.enumInputsOffset() = varRefMap().getBy(ZOrdinaryCategory.ENUM_INPUT).offset();
1150
1151    syn int FClass.booleanInputsOffset() = varRefMap().getBy(ZOrdinaryCategory.BOOLEAN_INPUT).offset();
1152
1153    syn int FClass.timeOffset() = varRefMap().getBy(ZCategory.TIME).offset();
1154
1155    syn int FClass.homotopyLambdaOffset() = varRefMap().getBy(ZCategory.HOMOTOPY_LAMBDA).offset();
1156
1157    // TODO: Remove!?
1158    syn boolean FVariable.shouldContribute() = !isAlias() && !inRecord() && !isForIndex();
1159   
1160    // TODO: Remove?!?
1161    syn boolean FDerivativeVariable.shouldContributeFiltered() = shouldContribute() && (myDifferentiatedVariable().asFVariable().stateSelectAttributeSet() || uses().size() > 0);
1162   
1163    public class FClass {
1164        public static <T1, T2 extends T1> Collection<T2> filterCollection(Collection<T1> input, Criteria<T1> filter) {
1165            Collection<T2> res = new ArrayList<T2>();
1166            for (T1 elm : input) {
1167                if (filter.test(elm))
1168                    res.add((T2)elm);
1169            }
1170            return res;
1171        }
1172       
1173        // TODO: Remove?!
1174        public static <T extends FVariable, C extends Set<T>> C intersectFVSet(
1175                C a, Collection<? extends FVariable> b) {
1176            try {
1177                // To avoid having to have different versions for different collections
1178                C res = (C) a.getClass().newInstance();
1179                res.addAll(a);
1180                res.retainAll(b);
1181                return res;
1182            } catch (IllegalAccessException e) {
1183            } catch (InstantiationException e) {
1184            }
1185            throw new IllegalArgumentException("First argument must be of class with public default constructor.");
1186        }
1187       
1188        public static final Criteria<FVariable> REAL_VARIABLE_FILTER = new Criteria<FVariable>() {
1189            @Override
1190            public boolean test(FVariable var) {
1191                return var.isReal();
1192            }
1193        };
1194       
1195        public static final Criteria<FVariable> INTEGER_VARIABLE_FILTER = new Criteria<FVariable>() {
1196            @Override
1197            public boolean test(FVariable var) {
1198                return var.isInteger();
1199            }
1200        };
1201       
1202        public static final Criteria<FVariable> BOOLEAN_VARIABLE_FILTER = new Criteria<FVariable>() {
1203            @Override
1204            public boolean test(FVariable var) {
1205                return var.isBoolean();
1206            }
1207        };
1208       
1209        public static final Criteria<FVariable> STRING_VARIABLE_FILTER = new Criteria<FVariable>() {
1210            @Override
1211            public boolean test(FVariable var) {
1212                return var.isString();
1213            }
1214        };
1215       
1216        public static final Criteria<FVariable> ENUM_VARIABLE_FILTER = new Criteria<FVariable>() {
1217            @Override
1218            public boolean test(FVariable var) {
1219                return var.isEnum();
1220            }
1221        };
1222       
1223    }
1224
1225
1226
1227
1228
1229
1230    syn int FClass.numReals() = reals().size();
1231    syn Collection<FVariable> FClass.reals() = varRefMap().getBy(ZType.REAL);
1232
1233    syn int FClass.numIntegers() = integers().size();
1234    syn Collection<FVariable> FClass.integers() = varRefMap().getBy(ZType.INTEGER);
1235
1236    syn int FClass.numEnums() = enums().size();
1237    syn Collection<FVariable> FClass.enums() = varRefMap().getBy(ZType.ENUM);
1238
1239    syn int FClass.numBooleans() = booleans().size();
1240    syn Collection<FVariable> FClass.booleans() = varRefMap().getBy(ZType.BOOLEAN);
1241
1242    syn int FClass.numStrings() = strings().size();
1243    syn Collection<FVariable> FClass.strings() = varRefMap().getBy(ZType.STRING);
1244
1245    syn int FClass.numIndependentConstants() = independentConstants().size();
1246    syn Collection<FVariable> FClass.independentConstants() = varRefMap().getBy(ParaDependency.INDEPENDENT, ZVariability.CONSTANT);
1247
1248    syn int FClass.numExternalObjectVariables() = externalObjectVariables().size();
1249    syn Collection<FVariable> FClass.externalObjectVariables() = varRefMap().getBy(ZType.EXTERNAL);
1250
1251    syn int FClass.independentRealConstantsOffset() = independentRealConstants().offset();
1252    syn int FClass.numIndependentRealConstants() = independentRealConstants().size();
1253    syn ZCategoryEntry FClass.independentRealConstants() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_REAL_CONSTANT);
1254
1255    syn int FClass.independentIntegerConstantsOffset() = independentIntegerConstants().offset();
1256    syn int FClass.numIndependentIntegerConstants() = independentIntegerConstants().size();
1257    syn ZCategoryEntry FClass.independentIntegerConstants() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_INTEGER_CONSTANT);
1258
1259    syn int FClass.independentEnumConstantsOffset() = independentEnumConstants().offset();
1260    syn int FClass.numIndependentEnumConstants() = independentEnumConstants().size();
1261    syn ZCategoryEntry FClass.independentEnumConstants() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_ENUM_CONSTANT);
1262
1263    syn int FClass.independentBooleanConstantsOffset() = independentBooleanConstants().offset();
1264    syn int FClass.numIndependentBooleanConstants() = independentBooleanConstants().size();
1265    syn ZCategoryEntry FClass.independentBooleanConstants() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_BOOLEAN_CONSTANT);
1266   
1267    syn int FClass.numIndependentStringConstants() = independentStringConstants().size();
1268    syn ZCategoryEntry FClass.independentStringConstants() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_STRING_CONSTANT);
1269
1270    // TODO: Is there such a thing as a dependent constant??
1271    syn int FClass.numDependentConstants() = dependentConstants().size();
1272    syn Collection<FVariable> FClass.dependentConstants() = varRefMap().getBy(ParaDependency.DEPENDENT, ZVariability.CONSTANT);
1273
1274    syn int FClass.dependentRealConstantsOffset() = dependentRealConstants().offset();
1275    syn int FClass.numDependentRealConstants() = dependentRealConstants().size();
1276    syn ZCategoryEntry FClass.dependentRealConstants() = varRefMap().getBy(ZOrdinaryCategory.DEPENDENT_REAL_CONSTANT);
1277
1278    syn int FClass.dependentIntegerConstantsOffset() = dependentIntegerConstants().offset();
1279    syn int FClass.numDependentIntegerConstants() = dependentIntegerConstants().size();
1280    syn ZCategoryEntry FClass.dependentIntegerConstants() = varRefMap().getBy(ZOrdinaryCategory.DEPENDENT_INTEGER_CONSTANT);
1281
1282    syn int FClass.dependentEnumConstantsOffset() = dependentEnumConstants().offset();
1283    syn int FClass.numDependentEnumConstants() = dependentEnumConstants().size();
1284    syn ZCategoryEntry FClass.dependentEnumConstants() = varRefMap().getBy(ZOrdinaryCategory.DEPENDENT_ENUM_CONSTANT);
1285
1286    syn int FClass.dependentBooleanConstantsOffset() = dependentBooleanConstants().offset();
1287    syn int FClass.numDependentBooleanConstants() = dependentBooleanConstants().size();
1288    syn ZCategoryEntry FClass.dependentBooleanConstants() = varRefMap().getBy(ZOrdinaryCategory.DEPENDENT_BOOLEAN_CONSTANT);
1289
1290    syn int FClass.numDependentStringConstants() = dependentStringConstants().size();
1291    syn ZCategoryEntry FClass.dependentStringConstants() = varRefMap().getBy(ZOrdinaryCategory.DEPENDENT_STRING_CONSTANT);
1292
1293    syn int FClass.numIndependentParameters() = independentParameters().size();
1294    syn Collection<FVariable> FClass.independentParameters() = varRefMap().getParameterBy(ParaDependency.INDEPENDENT);
1295   
1296    syn int FClass.numIndependentRealParameters() = independentRealParameters().size();
1297    syn Collection<FVariable> FClass.independentRealParameters() = varRefMap().getParameterBy(ParaDependency.INDEPENDENT, ZType.REAL);
1298   
1299    syn int FClass.numIndependentIntegerParameters() = independentIntegerParameters().size();
1300    syn Collection<FVariable> FClass.independentIntegerParameters() = varRefMap().getParameterBy(ParaDependency.INDEPENDENT, ZType.INTEGER);
1301   
1302    syn int FClass.numIndependentEnumParameters() = independentEnumParameters().size();
1303    syn Collection<FVariable> FClass.independentEnumParameters() = varRefMap().getParameterBy(ParaDependency.INDEPENDENT, ZType.ENUM);
1304   
1305    syn int FClass.numIndependentBooleanParameters() = independentBooleanParameters().size();
1306    syn Collection<FVariable> FClass.independentBooleanParameters() = varRefMap().getParameterBy(ParaDependency.INDEPENDENT, ZType.BOOLEAN);
1307   
1308    syn int FClass.numIndependentStringParameters() = independentStringParameters().size();
1309    syn Collection<FVariable> FClass.independentStringParameters() = varRefMap().getParameterBy(ParaDependency.INDEPENDENT, ZType.STRING);
1310   
1311    syn int FClass.numRegularIndependentParameters() = regularIndependentParameters().size();
1312    syn Collection<FVariable> FClass.regularIndependentParameters() = varRefMap().getBy(ParaDependency.INDEPENDENT, ZVariability.REGULAR_PARAMETER);
1313   
1314    syn int FClass.independentRealParametersOffset() = regularIndependentRealParameters().offset();
1315    syn int FClass.numRegularIndependentRealParameters() = regularIndependentRealParameters().size();
1316    syn ZCategoryEntry FClass.regularIndependentRealParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_REAL_REGULAR_PARAMETER);
1317
1318    syn int FClass.independentIntegerParametersOffset() = regularIndependentIntegerParameters().offset();
1319    syn int FClass.numRegularIndependentIntegerParameters() = regularIndependentIntegerParameters().size();
1320    syn ZCategoryEntry FClass.regularIndependentIntegerParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_INTEGER_REGULAR_PARAMETER);
1321
1322    syn int FClass.independentEnumParametersOffset() = regularIndependentEnumParameters().offset();
1323    syn int FClass.numRegularIndependentEnumParameters() = regularIndependentEnumParameters().size();
1324    syn ZCategoryEntry FClass.regularIndependentEnumParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_ENUM_REGULAR_PARAMETER);
1325   
1326    syn int FClass.independentBooleanParametersOffset() = regularIndependentBooleanParameters().offset();
1327    syn int FClass.numRegularIndependentBooleanParameters() = regularIndependentBooleanParameters().size();
1328    syn ZCategoryEntry FClass.regularIndependentBooleanParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_BOOLEAN_REGULAR_PARAMETER);
1329
1330    syn int FClass.numRegularIndependentStringParameters() = regularIndependentStringParameters().size();
1331    syn ZCategoryEntry FClass.regularIndependentStringParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_STRING_REGULAR_PARAMETER);
1332   
1333    syn int FClass.numStructuralIndependentParameters() = structuralIndependentParameters().size();
1334    syn Collection<FVariable> FClass.structuralIndependentParameters() = varRefMap().getBy(ParaDependency.INDEPENDENT, ZVariability.STRUCTURAL_PARAMETER);
1335   
1336    syn int FClass.numStructuralIndependentRealParameters() = structuralIndependentRealParameters().size();
1337    syn ZCategoryEntry FClass.structuralIndependentRealParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_REAL_STRUCTURAL_PARAMETER);
1338   
1339    syn int FClass.numStructuralIndependentIntegerParameters() = structuralIndependentIntegerParameters().size();
1340    syn ZCategoryEntry FClass.structuralIndependentIntegerParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_INTEGER_STRUCTURAL_PARAMETER);
1341   
1342    syn int FClass.numStructuralIndependentEnumParameters() = structuralIndependentEnumParameters().size();
1343    syn ZCategoryEntry FClass.structuralIndependentEnumParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_ENUM_STRUCTURAL_PARAMETER);
1344   
1345    syn int FClass.numStructuralIndependentBooleanParameters() = structuralIndependentBooleanParameters().size();
1346    syn ZCategoryEntry FClass.structuralIndependentBooleanParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_BOOLEAN_STRUCTURAL_PARAMETER);
1347   
1348    syn int FClass.numStructuralIndependentStringParameters() = structuralIndependentStringParameters().size();
1349    syn ZCategoryEntry FClass.structuralIndependentStringParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_STRING_STRUCTURAL_PARAMETER);
1350   
1351    syn int FClass.numFinalIndependentParameters() = finalIndependentParameters().size();
1352    syn Collection<FVariable> FClass.finalIndependentParameters() = varRefMap().getBy(ParaDependency.INDEPENDENT, ZVariability.FINAL_PARAMETER);
1353   
1354    syn int FClass.numFinalIndependentRealParameters() = finalIndependentRealParameters().size();
1355    syn ZCategoryEntry FClass.finalIndependentRealParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_REAL_FINAL_PARAMETER);
1356   
1357    syn int FClass.numFinalIndependentIntegerParameters() = finalIndependentIntegerParameters().size();
1358    syn ZCategoryEntry FClass.finalIndependentIntegerParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_INTEGER_FINAL_PARAMETER);
1359   
1360    syn int FClass.numFinalIndependentEnumParameters() = finalIndependentEnumParameters().size();
1361    syn ZCategoryEntry FClass.finalIndependentEnumParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_ENUM_FINAL_PARAMETER);
1362   
1363    syn int FClass.numFinalIndependentBooleanParameters() = finalIndependentBooleanParameters().size();
1364    syn ZCategoryEntry FClass.finalIndependentBooleanParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_BOOLEAN_FINAL_PARAMETER);
1365   
1366    syn int FClass.numFinalIndependentStringParameters() = finalIndependentStringParameters().size();
1367    syn ZCategoryEntry FClass.finalIndependentStringParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_STRING_FINAL_PARAMETER);
1368   
1369    syn int FClass.numEvalIndependentParameters() = evalIndependentParameters().size();
1370    syn Collection<FVariable> FClass.evalIndependentParameters() = varRefMap().getBy(ParaDependency.INDEPENDENT, ZVariability.STRUCTURAL_PARAMETER);
1371   
1372    syn int FClass.numEvalIndependentRealParameters() = evalIndependentRealParameters().size();
1373    syn ZCategoryEntry FClass.evalIndependentRealParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_REAL_EVAL_PARAMETER);
1374   
1375    syn int FClass.numEvalIndependentIntegerParameters() = evalIndependentIntegerParameters().size();
1376    syn ZCategoryEntry FClass.evalIndependentIntegerParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_INTEGER_EVAL_PARAMETER);
1377   
1378    syn int FClass.numEvalIndependentEnumParameters() = evalIndependentEnumParameters().size();
1379    syn ZCategoryEntry FClass.evalIndependentEnumParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_ENUM_EVAL_PARAMETER);
1380   
1381    syn int FClass.numEvalIndependentBooleanParameters() = evalIndependentBooleanParameters().size();
1382    syn ZCategoryEntry FClass.evalIndependentBooleanParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_BOOLEAN_EVAL_PARAMETER);
1383   
1384    syn int FClass.numEvalIndependentStringParameters() = evalIndependentStringParameters().size();
1385    syn ZCategoryEntry FClass.evalIndependentStringParameters() = varRefMap().getBy(ZOrdinaryCategory.INDEPENDENT_STRING_EVAL_PARAMETER);
1386   
1387    syn int FClass.numDependentParameters() = dependentParameters().size();
1388    syn Collection<FVariable> FClass.dependentParameters() = varRefMap().getParameterBy(ParaDependency.DEPENDENT);
1389
1390    syn int FClass.numDependentRealParameters() = dependentRealParameters().size();
1391    syn Collection<FVariable> FClass.dependentRealParameters() = varRefMap().getParameterBy(ParaDependency.DEPENDENT, ZType.REAL);
1392
1393    syn int FClass.numDependentIntegerParameters() = dependentIntegerParameters().size();
1394    syn Collection<FVariable> FClass.dependentIntegerParameters() = varRefMap().getParameterBy(ParaDependency.DEPENDENT, ZType.INTEGER);
1395
1396    syn int FClass.numDependentEnumParameters() = dependentEnumParameters().size();
1397    syn Collection<FVariable> FClass.dependentEnumParameters() = varRefMap().getParameterBy(ParaDependency.DEPENDENT, ZType.ENUM);
1398
1399    syn int FClass.numDependentBooleanParameters() = dependentBooleanParameters().size();
1400    syn Collection<FVariable> FClass.dependentBooleanParameters() = varRefMap().getParameterBy(ParaDependency.DEPENDENT, ZType.BOOLEAN);
1401   
1402    syn int FClass.numDependentStringParameters() = dependentStringParameters().size();
1403    syn Collection<FVariable> FClass.dependentStringParameters() = varRefMap().getParameterBy(ParaDependency.DEPENDENT, ZType.STRING);
1404   
1405    syn int FClass.dependentRealRegularParametersOffset() = dependentRealRegularParameters().offset();
1406    syn int FClass.numDependentRealRegularParameters() = dependentRealRegularParameters().size();
1407    syn ZCategoryEntry FClass.dependentRealRegularParameters() = varRefMap().getBy(ZOrdinaryCategory.DEPENDENT_REAL_REGULAR_PARAMETER);
1408
1409    syn int FClass.dependentIntegerRegularParametersOffset() = dependentIntegerRegularParameters().offset();
1410    syn int FClass.numDependentIntegerRegularParameters() = dependentIntegerRegularParameters().size();
1411    syn ZCategoryEntry FClass.dependentIntegerRegularParameters() = varRefMap().getBy(ZOrdinaryCategory.DEPENDENT_INTEGER_REGULAR_PARAMETER);
1412
1413    syn int FClass.dependentEnumRegularParametersOffset() = dependentEnumRegularParameters().offset();
1414    syn int FClass.numDependentEnumRegularParameters() = dependentEnumRegularParameters().size();
1415    syn ZCategoryEntry FClass.dependentEnumRegularParameters() = varRefMap().getBy(ZOrdinaryCategory.DEPENDENT_ENUM_REGULAR_PARAMETER);
1416   
1417    syn int FClass.dependentBooleanRegularParametersOffset() = dependentBooleanRegularParameters().offset();
1418    syn int FClass.numDependentBooleanRegularParameters() = dependentBooleanRegularParameters().size();
1419    syn ZCategoryEntry FClass.dependentBooleanRegularParameters() = varRefMap().getBy(ZOrdinaryCategory.DEPENDENT_BOOLEAN_REGULAR_PARAMETER);
1420   
1421    syn int FClass.numDependentStringRegularParameters() = dependentStringRegularParameters().size();
1422    syn ZCategoryEntry FClass.dependentStringRegularParameters() = varRefMap().getBy(ZOrdinaryCategory.DEPENDENT_STRING_REGULAR_PARAMETER);
1423   
1424    syn int FClass.realInitialParametersOffset() = realInitialParameters().offset();
1425    syn int FClass.numRealInitialParameters() = realInitialParameters().size();
1426    syn ZCategoryEntry FClass.realInitialParameters() = varRefMap().getBy(ZOrdinaryCategory.REAL_INITIAL_PARAMETER);
1427   
1428    syn int FClass.integerInitialParametersOffset() = integerInitialParameters().offset();
1429    syn int FClass.numIntegerInitialParameters() = integerInitialParameters().size();
1430    syn ZCategoryEntry FClass.integerInitialParameters() = varRefMap().getBy(ZOrdinaryCategory.INTEGER_INITIAL_PARAMETER);
1431   
1432    syn int FClass.enumInitialParametersOffset() = enumInitialParameters().offset();
1433    syn int FClass.numEnumInitialParameters() = enumInitialParameters().size();
1434    syn ZCategoryEntry FClass.enumInitialParameters() = varRefMap().getBy(ZOrdinaryCategory.ENUM_INITIAL_PARAMETER);
1435   
1436    syn int FClass.booleanInitialParametersOffset() = booleanInitialParameters().offset();
1437    syn int FClass.numBooleanInitialParameters() = booleanInitialParameters().size();
1438    syn ZCategoryEntry FClass.booleanInitialParameters() = varRefMap().getBy(ZOrdinaryCategory.BOOLEAN_INITIAL_PARAMETER);
1439   
1440    syn int FClass.numStringInitialParameters() = stringInitialParameters().size();
1441    syn ZCategoryEntry FClass.stringInitialParameters() = varRefMap().getBy(ZOrdinaryCategory.STRING_INITIAL_PARAMETER);
1442
1443    /**
1444     * Optimica specific but used in Modelica...
1445     */
1446    syn int FClass.numFreeParameters() = freeParameters().size();
1447    syn Collection<FVariable> FClass.freeParameters() = varRefMap().getBy(ZVariability.FREE_PARAMETER);
1448
1449
1450    syn int FClass.discreteRealVariablesOffset() = discreteRealVariables().offset();
1451    syn int FClass.numDiscreteRealVariables() = discreteRealVariables().size();
1452    syn ZCategoryEntry FClass.discreteRealVariables() = varRefMap().getBy(ZOrdinaryCategory.DISCRETE_REAL);
1453
1454    syn int FClass.discreteIntegerVariablesOffset() = discreteIntegerVariables().offset();
1455    syn int FClass.numDiscreteIntegerVariables() = discreteIntegerVariables().size();
1456    syn ZCategoryEntry FClass.discreteIntegerVariables() = varRefMap().getBy(ZOrdinaryCategory.DISCRETE_INTEGER);
1457
1458    syn int FClass.discreteEnumVariablesOffset() = discreteEnumVariables().offset();
1459    syn int FClass.numDiscreteEnumVariables() = discreteEnumVariables().size();
1460    syn ZCategoryEntry FClass.discreteEnumVariables() = varRefMap().getBy(ZOrdinaryCategory.DISCRETE_ENUM);
1461
1462    syn int FClass.discreteBooleanVariablesOffset() = discreteBooleanVariables().offset();
1463    syn int FClass.numDiscreteBooleanVariables() = discreteBooleanVariables().size();
1464    syn ZCategoryEntry FClass.discreteBooleanVariables() = varRefMap().getBy(ZOrdinaryCategory.DISCRETE_BOOLEAN);
1465
1466    syn int FClass.numDiscreteStringVariables() = discreteStringVariables().size();
1467    syn ZCategoryEntry FClass.discreteStringVariables() = varRefMap().getBy(ZOrdinaryCategory.DISCRETE_STRING);
1468
1469    syn int FClass.differentiatedRealVariablesOffset() = differentiatedRealVariables().offset();
1470    syn int FClass.numDifferentiatedRealVariables() = differentiatedRealVariables().size();
1471    syn ZCategoryEntry FClass.differentiatedRealVariables() = varRefMap().getBy(ZOrdinaryCategory.DIFFERENTIATED);
1472
1473    // TODO: This should be removed!
1474    syn lazy ArrayList<FVariable> FClass.differentiatedRealVariablesList() {
1475        ArrayList<FVariable> l = new ArrayList<FVariable>();
1476        for (FVariable fv : differentiatedRealVariables()) 
1477            l.add(fv);
1478        return l;
1479    }
1480    syn int FVariable.differentiatedRealVariableIndex() =
1481        myFClass().differentiatedRealVariablesList().indexOf(this);
1482
1483    syn lazy LinkedHashSet<FVariable> FClass.allDifferentiatedRealVariables() {
1484        LinkedHashSet<FVariable> set = new LinkedHashSet<FVariable>();
1485        set.addAll(differentiatedRealVariables());
1486        set.addAll(dynamicStates());
1487        return set;
1488    }
1489
1490    /**
1491     * Collection that contains all differentiated variables that has been
1492     * found to be dynamic states. All of these variables originates from
1493     * the original model.
1494     */
1495    coll LinkedHashSet<FRealVariable> FClass.dynamicStates()
1496      [new LinkedHashSet<FRealVariable>()] with add root FClass;
1497    FRealVariable contributes this when (isDynamicState())
1498      to FClass.dynamicStates() for myFClass();
1499    syn int FClass.numDynamicStates() = dynamicStates().size();
1500
1501    /**
1502     * Collection that contains all dynamic state variables introduced by the
1503     * compiler. This collection differs from dynamicStates() in that it
1504     * contains all the actual states.
1505     */
1506    coll LinkedHashSet<FDynamicStateVariable> FClass.dynamicStateVariables()
1507      [new LinkedHashSet<FDynamicStateVariable>()] with add root FClass;
1508    FDynamicStateVariable contributes this 
1509      to FClass.dynamicStateVariables() for myFClass();
1510    syn int FClass.numDynamicStateVariables() = dynamicStateVariables().size();
1511
1512    /**
1513     * Collection that contains all dynamic algebraic variables introduced by the
1514     * compiler.
1515     */
1516    coll LinkedHashSet<FDynamicAlgebraicVariable> FClass.dynamicAlgebraicVariables()
1517    [new LinkedHashSet<FDynamicAlgebraicVariable>()] with add root FClass;
1518      FDynamicAlgebraicVariable contributes this 
1519    to FClass.dynamicAlgebraicVariables() for myFClass();
1520    syn int FClass.numDynamicAlgebraicVariables() = dynamicAlgebraicVariables().size();
1521
1522    /**
1523     * Returns the same set as differentiatedRealVariablesSet, except derivatives with no
1524     * uses that were not introduced because of stateselect.
1525     */
1526    coll LinkedHashSet<FRealVariable> FClass.differentiatedRealVariablesFilteredSet() 
1527      [new LinkedHashSet<FRealVariable>()] with add root FClass;
1528    FDerExp contributes (FRealVariable) getFAccess().myFV() when getFAccess().myFV().isFVariable() && !inDeadIfBranch()
1529    to FClass.differentiatedRealVariablesFilteredSet() for myFClass();
1530    FDerivativeVariable contributes
1531        myDifferentiatedVariable().asFRealVariable() when (shouldContributeFiltered())
1532    to FClass.differentiatedRealVariablesFilteredSet() for myFClass();
1533    FDynamicStateVariable contributes this
1534    to FClass.differentiatedRealVariablesFilteredSet() for myFClass();
1535   
1536    /**
1537     * \brief Collection of all callables called by a partial function call
1538     * or kept as a component.
1539     */
1540    coll LinkedHashSet<FFunctionDecl> FClass.myFFunctionDeclsPartial() 
1541        [new LinkedHashSet<FFunctionDecl>()] with add root FClass;
1542    FPartialFunctionCall contributes myFCallable().actualFFunctionDecl() to FClass.myFFunctionDeclsPartial() for myFClass();
1543    FFunctionVariable contributes myFCallable().actualFFunctionDecl() when type().isFunction()
1544        to FClass.myFFunctionDeclsPartial() for myFClass();
1545   
1546    /**
1547     * \brief Collection of all FFunctionDecls called by a partial function call.
1548     */
1549    coll LinkedHashSet<FFunctionDecl> FClass.myFFunctionDeclsPartialCalled() 
1550        [new LinkedHashSet<FFunctionDecl>()] with add root FClass;
1551    FPartialFunctionCall contributes myFCallable().actualFFunctionDecl() to FClass.myFFunctionDeclsPartialCalled() for myFClass();
1552
1553    inh FVariable FIndicatorExp.myIndicatorVariable();
1554    eq FEquation.getChild().myIndicatorVariable()   = getLeft().asFAccessExp().myFV().asFVariable();
1555    eq FAssignStmt.getChild().myIndicatorVariable() = getLeft().asFAccessExp().myFV().asFVariable();
1556
1557    coll ArrayList<FDelayExp> FClass.myDelayExps()
1558        [new ArrayList<FDelayExp>()] with add root FClass;
1559    FDelayExp contributes this to FClass.myDelayExps() for myFClass();
1560   
1561    syn lazy int FDelayExp.myDelayIndex()  = myFClass().myDelayExps().indexOf(originalFExp());
1562    syn int FDelayIndicator.myDelayIndex() = myDelayExp().myDelayIndex();
1563   
1564    syn FDelayExp FDelayIndicator.myDelayExp() = myFClass().findDelayExp(myIndicatorVariable());
1565   
1566    syn lazy FDelayExp FClass.findDelayExp(FVariable indicator) {
1567        for (FDelayExp delayExp : myDelayExps()) {
1568            if (delayExp.hasIndicator(indicator)) {
1569                return delayExp;
1570            }
1571        }
1572        return null;
1573    }
1574   
1575    coll ArrayList<FSpatialDistExp> FClass.mySpatialDistExps()
1576        [new ArrayList<FSpatialDistExp>()] with add root FClass;
1577    FSpatialDistExp contributes this to FClass.mySpatialDistExps() for myFClass();
1578   
1579    syn lazy int FSpatialDistExp.mySpatialDistIndex()  = myFClass().mySpatialDistExps().indexOf(originalFExp());
1580    syn int FSpatialDistIndicator.mySpatialDistIndex() = mySpatialDistExp().mySpatialDistIndex();
1581   
1582    syn FSpatialDistExp FSpatialDistIndicator.mySpatialDistExp() = myFClass().findSpatialDistExp(myIndicatorVariable());
1583   
1584    syn lazy FSpatialDistExp FClass.findSpatialDistExp(FVariable indicator) {
1585        for (FSpatialDistExp spatialDistExp : mySpatialDistExps()) {
1586            if (spatialDistExp.hasIndicator(indicator)) {
1587                return spatialDistExp;
1588            }
1589        }
1590        return null;
1591    }
1592   
1593   
1594    inh boolean FExp.inDeadIfBranch();
1595    eq FIfEquation.getFAbstractEquation().inDeadIfBranch() = getTest().inDeadIfBranchTest(false);
1596    eq FIfEquation.getElse().inDeadIfBranch()              = getTest().inDeadIfBranchTest(true);
1597    eq FIfExp.getThenExp().inDeadIfBranch()                = getIfExp().inDeadIfBranchTest(false);
1598    eq FIfExp.getElseExp().inDeadIfBranch()                = getIfExp().inDeadIfBranchTest(true);
1599    eq FClass.getChild().inDeadIfBranch()                  = false;
1600    eq InstNode.getChild().inDeadIfBranch()                = false;
1601
1602    syn boolean FExp.inDeadIfBranchTest(boolean deadValue) = 
1603        (isConstantExp() && ceval().booleanValue() == deadValue) || inDeadIfBranch();
1604
1605    syn int FClass.numDerivativeVariables() = derivativeVariables().size();
1606    coll ArrayList<FDerivativeVariable> FClass.derivativeVariables() 
1607      [new ArrayList<FDerivativeVariable>()] with add root FClass;
1608    FDerivativeVariable contributes
1609        this when (shouldContribute())
1610    to FClass.derivativeVariables() for myFClass();
1611   
1612    syn int FClass.numVariables() = variables().size();
1613    coll ArrayList<FVariable> FClass.variables() 
1614      [new ArrayList<FVariable>()] with add root FClass;
1615    FVariable contributes
1616        this when !isParameter() && !isConstant() && !isPreVariable() && shouldContribute()
1617    to FClass.variables() for myFClass();
1618
1619    syn int FClass.numDiscreteVariables() = discreteVariables().size();
1620    syn Collection<FVariable> FClass.discreteVariables() = varRefMap().getBy(ZVariability.DISCRETE);
1621
1622    syn int FClass.numInitialParameters() = initialParameters().size();
1623    syn Collection<FVariable> FClass.initialParameters() = varRefMap().getBy(ZVariability.INITIAL_PARAMETER);
1624   
1625    syn boolean FAbstractVariable.isFixed() = true;
1626    eq FVariable.isFixed() = !isInitialParameter() && fixedAttribute();
1627   
1628    syn boolean FAbstractVariable.isInitialParameter() = false;
1629    eq FVariable.isInitialParameter()                  = variability().initialParameterVariability();
1630   
1631    syn boolean InstComponentDecl.isInitialParameter() = variability().initialParameterVariability();
1632   
1633    syn boolean ASTNode.containsFTimeExp() {
1634        for (ASTNode child : this)
1635            if (child.containsFTimeExp())
1636                return true;
1637        return false;
1638    }
1639    eq FTimeExp.containsFTimeExp() = true;
1640    syn lazy boolean FAbstractEquation.containsFTimeExp() = super.containsFTimeExp();
1641   
1642    syn boolean ASTNode.containsFHomotopyExp() {
1643        for (ASTNode child : this)
1644            if (child.containsFHomotopyExp())
1645                return true;
1646        return false;
1647    }
1648    eq FHomotopyExp.containsFHomotopyExp() = true;
1649    syn lazy boolean FAbstractEquation.containsFHomotopyExp() = super.containsFHomotopyExp();
1650    public boolean AbstractEquationBlock.containsFHomotopyExp() {
1651        for (FAbstractEquation eqn : allEquations()) {
1652            if (eqn.containsFHomotopyExp()) {
1653                return true;
1654            }
1655        }
1656        return false;
1657    }
1658   
1659    syn int FClass.numDiscretePreVariables() = discretePreVariables().size();
1660    syn lazy Collection<FVariable> FClass.discretePreVariables() {
1661        Collection<FVariable> l = new ArrayList<FVariable>();
1662        for (FVariable fv : discreteVariables()) {
1663            l.add((FVariable) lookupFV(fv.getFAccess().preName()));
1664        }
1665        for (FVariable fv : continuousVariablesUsedInPreInInitial()) {
1666            l.add((FVariable) lookupFV(fv.getFAccess().preName()));
1667        }
1668        return l;
1669    }
1670   
1671    syn int FClass.numAliasVariables() = aliasVariables().size();
1672    coll ArrayList<FVariable> FClass.aliasVariables() 
1673      [new ArrayList<FVariable>()] with add root FClass;
1674    FVariable contributes
1675        this when  !isParameter() && !isConstant() && isAlias()
1676    to FClass.aliasVariables() for myFClass();
1677
1678    syn int FClass.numAllVariables() = allVariables().size();
1679    syn lazy ArrayList<FVariable> FClass.allVariables() {
1680          ArrayList<FVariable> set = new ArrayList<FVariable>();
1681          for (FVariable fv : getFVariables()) {
1682                  set.add(fv);
1683              }
1684          for (FVariable fv : getAliasVariables()) {
1685                  set.add(fv);
1686              }
1687          return set;
1688    }
1689
1690    syn int FClass.numTempVariables() = tempVariables().size();
1691    coll ArrayList<FVariable> FClass.tempVariables() 
1692        [new ArrayList<FVariable>()] with add root FClass;
1693    FVariable contributes
1694        this when isTemporary() && shouldContribute()
1695    to FClass.tempVariables() for myFClass();
1696
1697    syn int FClass.numRealVariables() = realVariables().size();
1698    syn lazy Collection<FRealVariable> FClass.realVariables() = 
1699            filterCollection(variables(), REAL_VARIABLE_FILTER);
1700
1701    syn int FClass.numIntegerVariables() = integerVariables().size();
1702    syn lazy Collection<FIntegerVariable> FClass.integerVariables() =
1703            filterCollection(variables(), INTEGER_VARIABLE_FILTER);
1704
1705    syn int FClass.numEnumVariables() = enumVariables().size();
1706    syn lazy Collection<FEnumVariable> FClass.enumVariables() =
1707            filterCollection(variables(), ENUM_VARIABLE_FILTER);
1708
1709    syn int FClass.numBooleanVariables() = booleanVariables().size();
1710    syn lazy Collection<FBooleanVariable> FClass.booleanVariables() =
1711            filterCollection(variables(), BOOLEAN_VARIABLE_FILTER);
1712
1713    syn int FClass.numStringVariables() = stringVariables().size();
1714    syn lazy Collection<FStringVariable> FClass.stringVariables() =
1715            filterCollection(variables(), STRING_VARIABLE_FILTER);
1716
1717    syn int FClass.numAlgebraicContinousRealVariables() = algebraicContinousRealVariables().size();
1718    syn Collection<FVariable> FClass.algebraicContinousRealVariables() = varRefMap().getBy(ZOrdinaryCategory.CONTINUOUS);
1719
1720    syn int FClass.numNormalAlgebraicContinousRealVariables() = normalAlgebraicContinousRealVariables().size();
1721    syn lazy Collection<FVariable> FClass.normalAlgebraicContinousRealVariables() {
1722        // TODO: Refactor to new framework!
1723        Collection<FVariable> set = new LinkedHashSet<FVariable>();
1724        for (FVariable var : algebraicContinousRealVariables()) {
1725            set.add(var);
1726        }
1727        set.removeAll(dynamicStates());
1728        return set;
1729    }
1730
1731    public static final VarRefMap.CategoryFilter FClass.ALGEBRAIC_FILTER = new VarRefMap.CategoryFilter() {
1732        @Override
1733        protected boolean test(ZOrdinaryCategory category) {
1734            return category == ZOrdinaryCategory.CONTINUOUS || category.variability == ZVariability.DISCRETE;
1735        }
1736       
1737    };
1738
1739    syn Collection<FVariable> FClass.algebraicVariables() = varRefMap().getBy(ALGEBRAIC_FILTER);
1740
1741    syn lazy Collection<FVariable> FClass.normalAlgebraicVariables() {
1742        Collection<FVariable> set = new LinkedHashSet<FVariable>(algebraicVariables());
1743        set.removeAll(dynamicStates());
1744        return set;
1745    }
1746
1747    syn int FClass.numVariablesWithBindingExp() = variablesWithBindingExp().size();
1748    coll ArrayList<FVariable> FClass.variablesWithBindingExp() 
1749        [new ArrayList<FVariable>()] with add root FClass;
1750    FVariable contributes this when
1751        !isParameter() && !isConstant() && hasBindingExp() && shouldContribute()
1752        to FClass.variablesWithBindingExp() for myFClass();
1753
1754    syn int FClass.numRealVariablesWithBindingExp() = realVariablesWithBindingExp().size();
1755    syn lazy Collection<FVariable> FClass.realVariablesWithBindingExp() =
1756            filterCollection(variablesWithBindingExp(), REAL_VARIABLE_FILTER);
1757
1758    syn int FClass.numIntegerVariablesWithBindingExp() = integerVariablesWithBindingExp().size();
1759    syn lazy Collection<FVariable> FClass.integerVariablesWithBindingExp() =
1760            filterCollection(variablesWithBindingExp(), INTEGER_VARIABLE_FILTER);
1761
1762    syn int FClass.numEnumVariablesWithBindingExp() = enumVariablesWithBindingExp().size();
1763    syn lazy Collection<FVariable> FClass.enumVariablesWithBindingExp() =
1764            filterCollection(variablesWithBindingExp(), ENUM_VARIABLE_FILTER);
1765
1766    syn int FClass.numBooleanVariablesWithBindingExp() = booleanVariablesWithBindingExp().size();
1767    syn lazy Collection<FVariable> FClass.booleanVariablesWithBindingExp() =
1768            filterCollection(variablesWithBindingExp(), BOOLEAN_VARIABLE_FILTER);
1769
1770    syn int FClass.numStringVariablesWithBindingExp() = stringVariablesWithBindingExp().size();
1771    syn lazy Collection<FVariable> FClass.stringVariablesWithBindingExp() =
1772            filterCollection(variablesWithBindingExp(), STRING_VARIABLE_FILTER);
1773     
1774    syn int FClass.numInputs() = inputs().size();
1775    coll ArrayList<FVariable> FClass.inputs() 
1776        [new ArrayList<FVariable>()] with add root FClass;
1777    FVariable contributes
1778        this when isInput() && shouldContribute()
1779    to FClass.inputs() for myFClass();
1780
1781    syn int FVariable.inputIndex() =
1782        myFClass().inputs().indexOf(this); // TODO: Ouch indexOf in arraylist :(
1783
1784    syn int FClass.numRealInputs() = realInputs().size();
1785    syn lazy Collection<FVariable> FClass.realInputs() =
1786            filterCollection(inputs(), REAL_VARIABLE_FILTER);
1787   
1788    syn int FClass.numIntegerInputs() = integerInputs().size();
1789    syn lazy Collection<FVariable> FClass.integerInputs() =
1790            filterCollection(inputs(), INTEGER_VARIABLE_FILTER);
1791   
1792    syn int FClass.numEnumInputs() = enumInputs().size();
1793    syn lazy Collection<FVariable> FClass.enumInputs() =
1794            filterCollection(inputs(), ENUM_VARIABLE_FILTER);
1795
1796    syn int FClass.numBooleanInputs() = booleanInputs().size();
1797    syn lazy Collection<FVariable> FClass.booleanInputs() =
1798            filterCollection(inputs(), BOOLEAN_VARIABLE_FILTER);
1799
1800    syn int FClass.numStringInputs() = stringInputs().size();
1801    syn lazy Collection<FVariable> FClass.stringInputs() =
1802            filterCollection(inputs(), STRING_VARIABLE_FILTER);
1803
1804    syn int FClass.numOutputs() = outputs().size();
1805    coll ArrayList<FVariable> FClass.outputs() 
1806        [new ArrayList<FVariable>()] with add root FClass;
1807    FVariable contributes
1808        this when isOutput() && shouldContribute()
1809    to FClass.outputs() for myFClass();
1810
1811    syn int FClass.numRealOutputs() = realOutputs().size();
1812    syn lazy Collection<FVariable> FClass.realOutputs() =
1813            filterCollection(outputs(), REAL_VARIABLE_FILTER);
1814   
1815    syn int FClass.numIntegerOutputs() = integerOutputs().size();
1816    syn lazy Collection<FVariable> FClass.integerOutputs() =
1817            filterCollection(outputs(), INTEGER_VARIABLE_FILTER);
1818   
1819    syn int FClass.numEnumOutputs() = enumOutputs().size();
1820    syn lazy Collection<FVariable> FClass.enumOutputs() =
1821            filterCollection(outputs(), ENUM_VARIABLE_FILTER);
1822
1823    syn int FClass.numBooleanOutputs() = booleanOutputs().size();
1824    syn lazy Collection<FVariable> FClass.booleanOutputs() =
1825            filterCollection(outputs(), BOOLEAN_VARIABLE_FILTER);
1826
1827    syn int FClass.numStringOutputs() = stringOutputs().size();
1828    syn lazy Collection<FVariable> FClass.stringOutputs() =
1829            filterCollection(outputs(), STRING_VARIABLE_FILTER);
1830
1831    syn int FClass.numScalarEquations() {
1832       int res = 0;
1833       for (FAbstractEquation e : equations())
1834               res += e.numScalarEquations();
1835        for (FVariable fv : getFVariables())
1836            if (!fv.variability().parameterOrLess() && fv.hasBindingExp())
1837                res += fv.getBindingExp().type().numScalarElements();
1838       return res;
1839    }
1840   
1841               
1842    syn lazy int FClass.numScalarEquationsAtInitialization() {
1843        int res = 0;
1844        for (FAbstractEquation e : equations())
1845            res += e.numScalarEquations();
1846        return res;
1847    }
1848    syn int FClass.numEquations() = equations().size();
1849    syn lazy ArrayList<FAbstractEquation> FClass.equations() {
1850        ArrayList<FAbstractEquation> l = new ArrayList<FAbstractEquation>();
1851        for (FAbstractEquation e : getFAbstractEquations()) {
1852            if (!e.isIgnored()) {
1853                l.add(e);
1854            }
1855        }
1856        return l;
1857    }
1858
1859    syn ArrayList<FAbstractEquation> FClass.allEquations() {
1860        ArrayList<FAbstractEquation> l = new ArrayList<FAbstractEquation>();
1861        l.addAll(equations());
1862        l.addAll(initialEquations());
1863        l.addAll(getParameterEquations().toArrayList());
1864        return l;
1865    }
1866
1867    coll ArrayList<FAlgorithm> FClass.algorithms() 
1868        [new ArrayList<FAlgorithm>()] with add root FClass;
1869    FAlgorithm contributes this when !inFunction()
1870        to FClass.algorithms() for myFClass();
1871
1872    syn int FClass.numContinuousEquations() = continuousEquations().size();
1873    syn lazy ArrayList<FAbstractEquation> FClass.continuousEquations() {
1874        ArrayList<FAbstractEquation> l = new ArrayList<FAbstractEquation>();
1875        for (FAbstractEquation e : getFAbstractEquations()) {
1876            if (!e.isIgnored() && e.isContinuous()) {
1877                l.add(e);
1878            }
1879        }
1880        return l;
1881    }
1882
1883    syn int FClass.numContinuousNonMetaEquations() = continuousNonMetaEquations().size();
1884    syn lazy ArrayList<FAbstractEquation> FClass.continuousNonMetaEquations() {
1885        ArrayList<FAbstractEquation> l = new ArrayList<FAbstractEquation>();
1886        for (FAbstractEquation e : continuousEquations()) {
1887            if (!e.isMetaEquation()) {
1888                l.add(e);
1889            }
1890        }
1891        return l;
1892    }
1893
1894    syn int FClass.numScalarVariables() {
1895        int res = 0;
1896        for (FVariable fv : getFVariables())
1897            if (!fv.variability().parameterOrLess())
1898                res += fv.type().numScalarElements();
1899        return res;
1900    }
1901   
1902    syn int FType.numScalarElements() = size().numElements();
1903    eq FRecordType.numScalarElements() {
1904        int res = 0;
1905        for (FRecordComponentType c : getComponents())
1906            res += c.getFType().numScalarElements();
1907        return res * super.numScalarElements();
1908    }
1909
1910    syn int FAbstractEquation.numScalarEquations() = 1;
1911    eq FEquation.numScalarEquations()           = getLeft().type().numScalarElements();
1912    eq FConnectClause.numScalarEquations()      = getConnector1().type().numScalarElements();
1913    syn lazy int FAlgorithm.numScalarEquations() {
1914        Set<FVariable> assignedVars = new HashSet<FVariable>();
1915        for (FAccessExp use : FAccessExpsInLHS()) {
1916            if (!use.myFV().isUnknown() && !assignedVars.contains(use.myFV())) {
1917                FVariable fv = (FVariable) use.myFV();
1918                assignedVars.add(fv);
1919            }
1920        }
1921        return assignedVars.size();
1922
1923    }
1924    eq FIfWhenElseEquation.numScalarEquations() = numScalarEqnsInList(getFAbstractEquations());
1925    eq FForClauseE.numScalarEquations()         = 
1926        numScalarEqnsInList(getFAbstractEquations()) * numForElems(getFForIndexs());
1927    eq InstForClauseE.numScalarEquations()      = 
1928        numScalarEqnsInList(getFAbstractEquations()) * numForElems(getInstForIndexs());
1929    eq FFunctionCallEquation.numScalarEquations() {
1930        int res = 0;
1931        for (FFunctionCallLeft l : getLefts())
1932            res += l.numScalarElements();
1933        return res;
1934    }
1935   
1936    syn boolean FAbstractEquation.isMetaEquation() = numScalarEquations() == 0;
1937   
1938    syn int FFunctionCallLeft.numScalarElements() {
1939        int res = 0;
1940        if (hasFExp()) {
1941            for (FExp exp : flatChildFExps()) {
1942                res += exp.numScalarElements();
1943            }
1944        }
1945        return res;
1946    }
1947   
1948    syn int FExp.numScalarElements() = type().numScalarElements();
1949    eq FNoExp.numScalarElements() = 0;
1950
1951    public Iterable<FExp> FFunctionCallLeft.flatChildFExps() {
1952        ArrayList<FExp> res = new ArrayList<FExp>();
1953        getFExp().flatChildFExps(res);
1954        return res;
1955    }
1956   
1957    public void FExp.flatChildFExps(ArrayList<FExp> res) {
1958        res.add(this);
1959    }
1960   
1961    public void FArray.flatChildFExps(ArrayList<FExp> res) {
1962        for (FExp exp : getFExps()) {
1963            exp.flatChildFExps(res);
1964        }
1965    }
1966   
1967    public void FRecordConstructor.flatChildFExps(ArrayList<FExp> res) {
1968        for (FExp exp : getArgs()) {
1969            exp.flatChildFExps(res);
1970        }
1971    }
1972   
1973   
1974
1975    protected static int FAbstractEquation.numForElems(List<? extends CommonForIndex> list) {
1976        int res = 1;
1977        for (CommonForIndex i : list)
1978            res *= i.size().numElements();
1979        return res;
1980    }
1981
1982    protected static int FAbstractEquation.numScalarEqnsInList(List<FAbstractEquation> list) {
1983        int res = 0;
1984        for (FAbstractEquation e : list) 
1985            res += e.numScalarEquations();
1986        return res;
1987    }
1988   
1989   
1990    syn boolean FExp.isTimeEventGenerating() {
1991        throw new UnsupportedOperationException();
1992    }
1993    eq FRelExp.isTimeEventGenerating() =  myOptions().getBooleanOption("time_events") && myOptions().getBooleanOption("relational_time_events") && solutionForTime().isValidExp();
1994    eq FEqRelExp.isTimeEventGenerating() = false;
1995    eq FDelayExp.isTimeEventGenerating() = myOptions().getBooleanOption("time_events") && getDelay().variability().parameterOrLess();
1996    eq FSpatialDistExp.isTimeEventGenerating() = false;
1997   
1998    protected int FExp.checkIndex(int i) {
1999        if (i < 0) {
2000            throw new UnsupportedOperationException("Unknown switch index for relational operator, not in list of switches.");
2001        }
2002        return i;
2003    }
2004   
2005    syn int FClass.numSwitches() = numStateSwitches() + numTimeSwitches();
2006    syn int FClass.numStateSwitches() = relExpsWithStateEvent().size() + numSpatialDistSwitches() + numDelaySwitches();
2007    syn int FClass.numTimeSwitches() = relExpsWithTimeEvent().size();
2008   
2009    syn int FClass.numEventIndicators() = numStateSwitches();
2010   
2011    syn lazy ArrayList<FExp> FClass.switchExps() {
2012        ArrayList<FExp> res = new ArrayList<FExp>();
2013        res.addAll(stateEventExps());
2014        res.addAll(relExpsWithTimeEvent());
2015        return res;
2016    }
2017   
2018    syn lazy int FRelExp.mySwitchIndex()   = isTimeEventGenerating() ?
2019            checkIndex(myFClass().switchExps().indexOf(originalFExp())) + myFClass().delayExpsWithStateEvent().size() :
2020            myEventIndicatorIndex();
2021    syn int FDelayExp.mySwitchIndex() = myEventIndicatorIndex();
2022   
2023    syn lazy ArrayList<FExp> FClass.stateEventExps() {
2024        ArrayList<FExp> res = new ArrayList<FExp>();
2025        res.addAll(relExpsWithStateEvent());
2026        res.addAll(spatialDistExpsWithStateEvent());
2027        res.addAll(delayExpsWithStateEvent());
2028        return res;
2029    }
2030   
2031    syn lazy int FRelExp.myEventIndicatorIndex()   = checkIndex(myFClass().stateEventExps().indexOf(originalFExp()));
2032    syn lazy int FSpatialDistExp.myEventIndicatorIndex() = checkIndex(myFClass().stateEventExps().indexOf(originalFExp()));
2033    syn lazy int FDelayExp.myEventIndicatorIndex() = myFClass().relExpsWithStateEvent().size() + myDelayEventIndicatorIndex();
2034   
2035    syn lazy ArrayList<FExp> FClass.timeEventExps() {
2036        ArrayList<FExp> res = new ArrayList<FExp>();
2037        res.addAll(sampleExpsWithTimeEvent());
2038        res.addAll(relExpsWithTimeEvent());
2039        return res;
2040    }
2041   
2042    coll ArrayList<FSampleExp> FClass.sampleExpsWithTimeEvent() 
2043        [new ArrayList<FSampleExp>()] with add root FClass;
2044    FSampleExp contributes this when generatesEventInDAE()
2045        to FClass.sampleExpsWithTimeEvent() for myFClass();
2046   
2047    syn int FClass.numSpatialDistSwitches() = spatialDistExpsWithStateEvent().size();
2048    coll ArrayList<FSpatialDistExp> FClass.spatialDistExpsWithStateEvent() 
2049        [new ArrayList<FSpatialDistExp>()] with add root FClass;
2050    FSpatialDistExp contributes this when generatesEventInDAE()
2051        to FClass.spatialDistExpsWithStateEvent() for myFClass();
2052   
2053    syn int FClass.numDelaySwitches() = 2*delayExpsWithStateEvent().size();
2054    coll ArrayList<FDelayExp> FClass.delayExpsWithStateEvent() 
2055        [new ArrayList<FDelayExp>()] with add root FClass;
2056    FDelayExp contributes this when generatesEventInDAE() && !isTimeEventGenerating()
2057        to FClass.delayExpsWithStateEvent() for myFClass();
2058   
2059   
2060    syn int FDelayExp.myDelayEventIndicatorIndex() = 2*checkIndex(myFClass().delayExpsWithStateEvent().indexOf(originalFExp()));
2061   
2062   
2063    syn int FClass.numGuardExpInEquations() = guardExpInEquations().size();
2064    syn int FClass.numGuardExpInInitialEquations() = guardExpInInitialEquations().size();
2065    syn int FExp.guardExpInEquationsIndex() = myFClass().guardExpInEquations().indexOf(this);
2066    syn int FExp.guardExpInInitialEquationsIndex() = myFClass().guardExpInInitialEquations().indexOf(this);
2067
2068    coll ArrayList<FExp> FClass.guardExpInEquations() 
2069        [new ArrayList<FExp>()] with addAll root FlatRoot;
2070    FWhenEquation contributes getTest().guards() when getTest().inEquationSection()
2071        to FClass.guardExpInEquations() for myFClass();
2072    FWhenStmt contributes guards() when inEquationSection()
2073        to FClass.guardExpInEquations() for myFClass();
2074
2075    coll ArrayList<FExp> FClass.guardExpInInitialEquations() 
2076        [new ArrayList<FExp>()] with addAll root FlatRoot;
2077    FWhenEquation contributes getTest().guards() when getTest().inInitialEquationSection()
2078        to FClass.guardExpInInitialEquations() for myFClass();
2079    FWhenStmt contributes guards() when inInitialEquationSection()
2080        to FClass.guardExpInInitialEquations() for myFClass(); 
2081
2082    coll Set<FExp> FAbstractEquation.transformedGuards() [new HashSet<FExp>()] 
2083        with add root FAbstractEquation;
2084    FIfExp contributes getIfExp() when isWhen()
2085        to FAbstractEquation.transformedGuards() for myFEquation();
2086    FIfEquation contributes getTest() when isWhen()
2087        to FAbstractEquation.transformedGuards() for this;
2088
2089    syn ArrayList<FExp> FWhenStmt.guards() {
2090        ArrayList<FExp> l = new ArrayList<FExp>();
2091        for (FIfWhenClause clause : getFIfWhenClauses()) {
2092            l.addAll(clause.getTest().guards());
2093        }
2094        return l;
2095    }
2096
2097    syn ArrayList<FExp> FExp.guards() {
2098        ArrayList<FExp> l = new ArrayList<FExp>();
2099        l.add(this);
2100        return l;
2101    }
2102    eq FArray.guards() {
2103        ArrayList<FExp> l = new ArrayList<FExp>();
2104        for (FExp e : childFExps())
2105            l.add(e);
2106        return l;
2107    }
2108
2109    syn int FSmoothExp.order() = getOrder().ceval().intValue(); 
2110
2111    /**
2112     * Check if an expression will generate an event. Parameters with
2113     * fixed=false are considered to generate events.
2114     */
2115    syn boolean FExp.generatesEvent() = generatesEvent(true);
2116
2117    /**
2118     * Check if an expression will generate an event.
2119     *
2120     * @param checkInitialParameters  Controls whether parameters with fixed = false should be
2121     *                                 considered to generate events.
2122     */
2123    syn boolean FExp.generatesEvent(boolean checkInitialParameters) = generatesEvent(false, checkInitialParameters);
2124
2125    /**
2126     * Check if an expression will generate an event.
2127     *
2128     * @param ignoreVariability        Controls whether variability should be ignored.
2129     * @param checkInitialParameters   Controls whether parameters with fixed = false should be
2130     *                                 considered to generate events.
2131     */
2132    syn boolean FExp.generatesEvent(boolean ignoreVariability, boolean checkInitialParameters) =
2133            inEventGeneratingLocation() && hasEventGeneratingType() &&
2134            (ignoreVariability || hasEventGeneratingVariability(checkInitialParameters)) &&
2135            myOptions().getBooleanOption("generate_event_switches");
2136
2137    /**
2138     * Check if an expression will generate an event.
2139     * Does not check context further than expressions.
2140     */
2141    syn boolean FExp.hasEventGeneratingVariability(boolean checkInitialParameters) =
2142            !variability().parameterOrLess() || (checkInitialParameters && variability().initialParameterVariability());
2143
2144    syn boolean FExp.inEventGeneratingLocation() = !inFunction() && !inNoEventExp() && !inSmoothExp(myOptions().getBooleanOption("disable_smooth_events") ? 0 : 1);
2145
2146    syn boolean FExp.hasEventGeneratingType() = false;
2147    eq FRelExp.hasEventGeneratingType()       = isRealComparison();
2148    eq FEventGenExp.hasEventGeneratingType()  = argType().isReal();
2149    eq FSpatialDistExp.hasEventGeneratingType() = true;
2150    eq FDelayExp.hasEventGeneratingType()     = true;
2151    eq FSampleExp.hasEventGeneratingType()    = true;
2152    eq FActualStream.hasEventGeneratingType() = true;
2153   
2154    syn boolean FExp.generatesEventInDAE() = generatesEventInDAE(originalFExp());
2155    syn boolean FRelExp.generatesEventInInitDAE() = generatesEventInInitDAE(originalFExp());
2156   
2157    syn boolean FExp.generatesEventInDAE(FExp orig) = inEquationSection() && orig==this && generatesEvent(false);
2158    syn boolean FRelExp.generatesEventInInitDAE(FExp orig) =
2159            (inInitialEquationSection() || (inEquationSection() && variability().initialParameterVariability()))
2160            && orig==this && generatesEvent(true);
2161   
2162    coll ArrayList<FRelExp> FClass.relExpsWithEvent() 
2163        [new ArrayList<FRelExp>()] with add root FClass;
2164    FRelExp contributes this when generatesEventInDAE() 
2165        to FClass.relExpsWithEvent() for myFClass();
2166   
2167    syn ArrayList<FRelExp> FClass.relExpsWithStateEvent() {
2168        ArrayList<FRelExp> res = new ArrayList<FRelExp>();
2169        for (FRelExp exp : relExpsWithEvent()) {
2170            if (!exp.isTimeEventGenerating()) {
2171                res.add(exp);
2172            }
2173        }
2174        return res;
2175    }
2176   
2177    syn ArrayList<FRelExp> FClass.relExpsWithTimeEvent() {
2178        ArrayList<FRelExp> res = new ArrayList<FRelExp>();
2179        for (FRelExp exp : relExpsWithEvent()) {
2180            if (exp.isTimeEventGenerating()) {
2181                res.add(exp);
2182            }
2183        }
2184        return res;
2185    }
2186
2187    coll ArrayList<FRelExp> FAbstractEquation.relExpInEquation() 
2188        [new ArrayList<FRelExp>()] with add root FAbstractEquation;
2189    FRelExp contributes this when generatesEventInDAE(this)
2190    to FAbstractEquation.relExpInEquation() for myFEquation();
2191
2192    coll ArrayList<FRelExp> FStatement.relExpInStmt() 
2193        [new ArrayList<FRelExp>()] with add root FStatement;
2194    FRelExp contributes this when generatesEventInDAE()
2195    to FStatement.relExpInStmt() for myFStatement();
2196   
2197    coll ArrayList<FDelayExp> FAbstractEquation.delayExpInEquation() 
2198        [new ArrayList<FDelayExp>()] with add root FAbstractEquation;
2199    FDelayExp contributes this when generatesEventInDAE()
2200    to FAbstractEquation.delayExpInEquation() for myFEquation();
2201
2202    coll ArrayList<FDelayExp> FStatement.delayExpInStmt() 
2203        [new ArrayList<FDelayExp>()] with add root FStatement;
2204    FDelayExp contributes this when generatesEventInDAE()
2205    to FStatement.delayExpInStmt() for myFStatement();
2206           
2207    coll ArrayList<FSpatialDistExp> FAbstractEquation.spatialDistExpInEquation() 
2208        with add root FAbstractEquation;
2209    FSpatialDistExp contributes this when generatesEventInDAE()
2210    to FAbstractEquation.spatialDistExpInEquation() for myFEquation();
2211
2212    coll ArrayList<FSpatialDistExp> FStatement.spatialDistExpInStmt() 
2213        with add root FStatement;
2214    FSpatialDistExp contributes this when generatesEventInDAE()
2215    to FStatement.spatialDistExpInStmt() for myFStatement();
2216   
2217    inh FStatement FExp.myFStatement();
2218    inh FStatement FStatement.myFStatement();
2219    inh FStatement FIfWhenClause.myFStatement();
2220    eq FStatement.getChild().myFStatement()        = this;
2221    eq FAbstractEquation.getChild().myFStatement() = null;
2222    eq Root.getChild().myFStatement()              = null;
2223   
2224    syn int FClass.numInitialEquations() = initialEquations().size(); 
2225    syn lazy int FClass.numInitialScalarEquations() {
2226        int res = 0;
2227        for (FAbstractEquation e : initialEquations())
2228            res += e.numScalarEquations();
2229        return res;
2230    }
2231    syn lazy ArrayList<FAbstractEquation> FClass.initialEquations() {
2232        ArrayList<FAbstractEquation> l = new ArrayList<FAbstractEquation>();
2233        for (FAbstractEquation e : getFInitialEquations()) {
2234            l.add(e);
2235        }
2236        return l;
2237    }
2238
2239    syn ArrayList<FAbstractEquation> FClass.normalEquations() = equations();
2240
2241    syn int FClass.numInitialGuessEquations() {
2242        int n_eq = 0;
2243        for (FRealVariable fv : realVariables()) {
2244            if (!fv.isFixed()) {
2245                n_eq++;
2246            }
2247        }
2248        return n_eq;
2249    }
2250   
2251    syn int FClass.numInitialEventIndicators() = numRelExpInInitialEquations();
2252   
2253    syn ArrayList<FRelExp> FClass.eventExpInInitialEquations() = relExpInInitialEquations();
2254   
2255    syn int FClass.numRelExpInInitialEquations() = relExpInInitialEquations().size();
2256    coll ArrayList<FRelExp> FClass.relExpInInitialEquations()
2257        [new ArrayList<FRelExp>()] with add root FClass;
2258    FRelExp contributes this when generatesEventInInitDAE()
2259    to FClass.relExpInInitialEquations() for myFClass();
2260
2261    coll ArrayList<FRelExp> FAbstractEquation.relExpInInitialEquation() 
2262        [new ArrayList<FRelExp>()] with add root FAbstractEquation;
2263    FRelExp contributes this when generatesEventInInitDAE(this)
2264    to FAbstractEquation.relExpInInitialEquation() for myFEquation();
2265   
2266    syn int FRelExp.relExpInInitialEquationsIndex()  = checkIndex(myFClass().relExpInInitialEquations().indexOf(originalFExp()));
2267
2268    /**
2269     * Collects event generating expressions in this statements
2270     */
2271    coll ArrayList<FExp> FAbstractEquation.eventGenExps() 
2272        [new ArrayList<FExp>()] with add root FClass;
2273    FExp contributes this
2274        when generatesEvent()
2275        to FAbstractEquation.eventGenExps()
2276        for myFEquation();
2277/* 
2278
2279    coll ArrayList<FVariable> FClass.structuralParameters() [new ArrayList<FVariable>()] with add root FClass;
2280    FAccessExp contributes
2281        (FVariable)myFV() when inArraySubscripts()
2282    to FClass.structuralParameters() for myFClass();
2283
2284    coll ArrayList<FEquation> FVariable.variableIncidence() [new ArrayList<FEquation>()] with add root FClass;
2285    FAccessExp contributes
2286        myFEquation() when inFEquation()
2287    to FVariable.variableIncidence() for (FVariable)myFV();
2288   
2289    syn lazy ArrayList<ArrayList> FClass.variableIncidence() {
2290        ArrayList<ArrayList> l = new ArrayList<ArrayList>();
2291        for (FVariable fv : variables()) {
2292           l.add(fv.variableIncidence());
2293       }
2294        return l;
2295   
2296    }
2297   
2298    */
2299   
2300    /**
2301     * Utility function that returns true if this equation on the form zero
2302     * equal to zero.
2303     */
2304    syn boolean FAbstractEquation.isZeroEquation() = false;
2305    eq FEquation.isZeroEquation() = getLeft().isLiteralZero() && getRight().isLiteralZero();
2306   
2307   
2308    inh Set<FVariable> FExp.boundParameters();
2309    eq FVariable.getBindingExp().boundParameters()       = Collections.singleton(this);
2310    eq Root.getChild().boundParameters()                 = Collections.emptySet();
2311    eq FEquation.getRight().boundParameters()            = boundParameters();
2312    eq FFunctionCallEquation.getCall().boundParameters() = boundParameters();
2313
2314    syn Set<FVariable> FAbstractEquation.boundParameters() = Collections.emptySet();
2315    eq FEquation.boundParameters() {
2316        if (isParameterEquation()) {
2317            return getLeft().referencedParametersInFExp();
2318        } else {
2319            return Collections.emptySet();
2320        }
2321    }
2322   
2323    syn Set<FVariable> FAbstractEquation.RHSVariables() = Collections.emptySet();
2324    eq FEquation.RHSVariables() {
2325        if (isParameterEquation()) {
2326            return getRight().referencedParametersInFExp();
2327        } else {
2328            return Collections.emptySet();
2329        }
2330    }
2331       
2332    eq FFunctionCallEquation.boundParameters() { 
2333        if (isParameterEquation()) { 
2334            return referencedParametersInLHS(); 
2335        } else {
2336            return Collections.emptySet();
2337        }
2338    }
2339   
2340    syn Set<FVariable> FAbstractVariable.myParameterDependencies() = Collections.emptySet();
2341    syn lazy Set<FVariable> FVariable.myParameterDependencies() {
2342        HashSet<FVariable> varSet = new HashSet<FVariable>();
2343        if (hasParameterEquation()) {
2344            for (FVariable vv: parameterEquation().RHSVariables()) {
2345                varSet.addAll(vv.myParameterDependencies());
2346            }
2347            return varSet;
2348        } else { //Base case
2349            varSet.add(this);
2350            return varSet;
2351        }
2352    }
2353   
2354    inh boolean FExp.inFEquation();
2355    eq FAbstractEquation.getChild().inFEquation()=true;
2356    eq Root.getChild().inFEquation()=false;
2357   
2358    inh FAbstractEquation FExp.myFEquation();
2359    inh FAbstractEquation FStatement.myFEquation();
2360    eq FAbstractEquation.getChild().myFEquation() = this;
2361    eq Root.getChild().myFEquation()              = null;
2362   
2363    inh FClass FAbstractVariable.myFClass();
2364    inh FClass FExp.myFClass();
2365    inh FClass FType.myFClass();
2366    inh FClass CommonAccess.myFClass();
2367    inh FClass FAccess.myFClass();
2368    inh FClass FFunctionDecl.myFClass();
2369    inh FClass FRecordDecl.myFClass();
2370    inh FClass FAlgorithm.myFClass();
2371    inh FClass FAbstractEquation.myFClass();
2372    inh FClass FStatement.myFClass();
2373    inh FClass FFunctionCallLeft.myFClass();
2374    inh lazy FClass FExternalStmt.myFClass();
2375    eq FClass.getChild().myFClass() = this;
2376    eq Root.getChild().myFClass() = null; 
2377   
2378    public Iterable<FAbstractEquation> FExp.enclosingEquationsIterator() {
2379        return myFEquation().enclosingEquationsIterator();
2380    }
2381
2382    public Iterable<FAbstractEquation> FStatement.enclosingEquationsIterator() {
2383        return myFEquation().enclosingEquationsIterator();
2384    }
2385   
2386    inh FAbstractEquation FAbstractEquation.enclosingEquation();
2387    eq FAbstractEquation.getChild().enclosingEquation() = this;
2388    eq Root.getChild().enclosingEquation()              = null;
2389   
2390    /**
2391     * Returns the outermost enclosing equation or the equation itself if it is
2392     * the outermost.
2393     */
2394    syn FAbstractEquation FAbstractEquation.outermostEnclosingEquation() {
2395        FAbstractEquation enclosing = this;
2396        FAbstractEquation next = enclosingEquation();
2397        while (next != null) {
2398            enclosing = next;
2399            next = enclosing.enclosingEquation();
2400        }
2401        return enclosing;
2402    }
2403   
2404    /**
2405     * Returns an iterable that can be used to iterate over all surounding
2406     * equations (including this one).
2407     */
2408    public Iterable<FAbstractEquation> FAbstractEquation.enclosingEquationsIterator() {
2409        return new Iterable<FAbstractEquation>() {
2410
2411            @Override
2412            public Iterator<FAbstractEquation> iterator() {
2413                return new Iterator<FAbstractEquation>() {
2414
2415                    private FAbstractEquation next = FAbstractEquation.this;
2416                   
2417                    @Override
2418                    public boolean hasNext() {
2419                        return next != null;
2420                    }
2421
2422                    @Override
2423                    public FAbstractEquation next() {
2424                        FAbstractEquation res = next;
2425                        next = next.enclosingEquation();
2426                        return res;
2427                    }
2428
2429                    @Override
2430                    public void remove() {
2431                        throw new UnsupportedOperationException();
2432                    }
2433                   
2434                };
2435            }
2436           
2437        };
2438    }
2439   
2440    syn lazy boolean FVariable.isIndependentConstant() = isConstant();
2441    syn lazy boolean FVariable.isDependentConstant() = false;
2442   
2443    syn boolean FAbstractVariable.isDependentParameter() = false;
2444    syn lazy boolean FVariable.isDependentParameter() = 
2445        isParameter() && !isIndependentParameter();
2446   
2447    syn boolean FAbstractVariable.isIndependentParameter() = false;
2448    syn lazy boolean FVariable.isIndependentParameter() =
2449            isParameter() && !isInitialParameter() && !hasParameterEquation() && 
2450            (!hasBindingExp() || getBindingExp().isIndependentParameterExp());
2451   
2452    syn lazy boolean FVariable.isRegularIndependentParameter() =
2453        isIndependentParameter() && !variability().knownParameterOrLess();
2454    syn lazy boolean FVariable.isStructuralIndependentParameter() =
2455        isIndependentParameter() && variability().knownParameterOrLess();
2456    syn lazy boolean FVariable.isFinalIndependentParameter() =
2457        false; // TODO
2458    syn lazy boolean FVariable.isEvalIndependentParameter() =
2459        false; // TODO
2460
2461    syn boolean FExp.isIndependentParameterExp() = isConstantExp() && !hasCompositeFunc();
2462   
2463    inh boolean FAbstractEquation.isParameterEquation();
2464    eq FClass.getParameterEquation().isParameterEquation() = true;
2465    eq Root.getChild().isParameterEquation() = false;
2466   
2467    inh boolean FAbstractEquation.isNormalEquation();
2468    eq FClass.getFAbstractEquation().isNormalEquation() = true;
2469    eq FClass.getChild().isNormalEquation()             = false;
2470    eq InstNode.getChild().isNormalEquation()           = true;
2471    eq Root.getChild().isNormalEquation()               = false;
2472   
2473    inh List<FAbstractEquation> FAbstractEquation.myFAbstractEquationList();
2474    eq FClass.getFAbstractEquation().myFAbstractEquationList() = getFAbstractEquations();
2475    eq FClass.getFInitialEquation().myFAbstractEquationList() = getFInitialEquations();
2476    eq FClass.getParameterEquation().myFAbstractEquationList() = getParameterEquations();
2477    eq FClass.getChild().myFAbstractEquationList() = null;
2478    eq Root.getChild().myFAbstractEquationList() = null;
2479   
2480    coll ArrayList<FExp> FAbstractEquation.replacedAtInitialExps()
2481        [new ArrayList<FExp>()] with add root FAbstractEquation;
2482    FDelayExp contributes this
2483        to FAbstractEquation.replacedAtInitialExps() for myFEquation();
2484    FSpatialDistExp contributes this
2485        to FAbstractEquation.replacedAtInitialExps() for myFEquation();
2486   
2487    syn boolean FAbstractEquation.replacedAtInitialization() = 
2488            isWhen() || replacedAtInitialExps().size() > 0;
2489    eq FAlgorithm.replacedAtInitialization() {
2490        if (super.replacedAtInitialization())
2491            return true;
2492       
2493        /*
2494         * Even if there are no when statements, there might still be discrete
2495         * variables which are dependent on their pre() variables
2496         */
2497        Set<FVariable> notDefSet = referencedFVariablesInLHS();
2498        notDefSet.removeAll(defSet());
2499        for (FVariable fv : notDefSet)
2500            if (fv.isDiscrete())
2501                return true;
2502        return false;
2503    }
2504   
2505    syn List<FAbstractEquation> FAbstractEquation.getInitialEquationList() {
2506        List<FAbstractEquation> l = new List<FAbstractEquation>();
2507        if (replacedAtInitialization()) {
2508            l.add((FAbstractEquation) copySymbolic());
2509        }
2510        return l;
2511    }
2512   
2513    eq FIfEquation.getInitialEquationList() {
2514        return createInitialEquationList();
2515    }
2516   
2517    syn List<FAbstractEquation> FIfWhenElseEquation.createInitialEquationList() {
2518        List<FAbstractEquation> l = new List<FAbstractEquation>();
2519        for (FAbstractEquation e : getFAbstractEquations()) {
2520            if (e.replacedAtInitialization()) {
2521                l.addAll(e.getInitialEquations());
2522            } else {
2523                l.add(e.copySymbolic());
2524            }
2525        }
2526        return l;
2527    }
2528   
2529    eq FIfWhenEquation.createInitialEquationList() {
2530        if (getTest().isInitialGuard())
2531            return super.createInitialEquationList();
2532        else if (hasElse())
2533            return getElse().createInitialEquationList();
2534        else
2535            return new List<FAbstractEquation>();
2536    }
2537   
2538
2539    rewrite FIfExp {
2540        when (isWhen() && isInitial()) to FExp {
2541            if (getIfExp().isInitialGuard())
2542                return getThenExp();
2543            else
2544                return getElseExp();
2545        }
2546    }
2547   
2548    rewrite FDelayExp {
2549        when (isInitial()) to FExp {
2550            return getFExp().copySymbolic();
2551        }
2552    }
2553   
2554    rewrite FSpatialDistExp {
2555        when (isInitial() && !isFunctionCallClause()) to FExp {
2556            return createInitialReplacement(false);
2557        }
2558    }
2559   
2560    public FExp FSpatialDistExp.createInitialReplacement(boolean second) {
2561        int size = getInitialValues().size().numElements();
2562        return new FIfExp(getPositiveVelocity().copySymbolic(),
2563                getInitialValues().getArray().get(second ? size : 1).copySymbolic(), 
2564                getInitialValues().getArray().get(second ? 1 : size).copySymbolic());
2565    }
2566   
2567    eq FFunctionCallEquation.getInitialEquationList() {
2568        if (getCall() instanceof FSpatialDistExp) {
2569            FSpatialDistExp call = (FSpatialDistExp) getCall();
2570            ArrayList<FAbstractEquation> l = new ArrayList<FAbstractEquation>();
2571            if (getNumLeft() > 0 && getLeft(0).hasFExp()) {
2572                l.add(new FEquation(getLeft(0).getFExp().copySymbolic(), call.createInitialReplacement(false)));
2573            }
2574            if (getNumLeft() > 1 && getLeft(1).hasFExp()) {
2575                l.add(new FEquation(getLeft(1).getFExp().copySymbolic(), call.createInitialReplacement(true)));
2576            }
2577            return new List<FAbstractEquation>(l);
2578        }
2579        return super.getInitialEquationList();
2580    }
2581   
2582    eq FAlgorithm.getInitialEquationList() {
2583        ArrayList<FAbstractEquation> l = new ArrayList<FAbstractEquation>();
2584       
2585        // Keeps FAccessExps in lhs which have not been removed
2586        Set<FAccessExp> usesLHS = FAccessExpsInLHS();
2587       
2588        // Keeps track of which variables are definetly set
2589        Set<FVariable> fvSet  = new HashSet<FVariable>();
2590        Set<FVariable> fvUse  = new HashSet<FVariable>();
2591       
2592        // Create a new algorithm with some statements removed
2593        ArrayList<FStatement> stmts = new ArrayList<FStatement>();
2594        for (FStatement stmt : getFStatements()) {
2595            stmt.addAsInitial(stmts, usesLHS, fvSet, fvUse);
2596        }
2597       
2598        Set<FVariable> lhs = lookupFVariablesInSet(usesLHS);
2599
2600        // Add initial statements for variables which are not definetly set
2601        // in the new algorithm
2602        ArrayList<FStatement> initStmts = new ArrayList<FStatement>();
2603        for (FVariable fv : lhs)
2604            if (!fvSet.contains(fv))
2605                initStmts.add(new FAssignStmt(fv.createAccessExp(), fv.createAlgorithmArgument(true)));
2606        for (FStatement stmt : stmts)
2607            initStmts.add(stmt);
2608        if (initStmts.size() > 0)
2609            l.add(new FAlgorithm(new List<FStatement>(initStmts)));
2610       
2611        // Create equations for variables which are no longer assigned
2612        // in the new algorithm
2613        Set<FVariable> removedFVs = referencedFVariablesInLHS();
2614        removedFVs.removeAll(lhs);
2615        for (FVariable fv : removedFVs)
2616            l.add(new FEquation(fv.createAccessExp(), fv.createFPreExp()));
2617       
2618        return new List<FAbstractEquation>(l);
2619    }
2620   
2621   
2622    public void FStatement.addAsInitial(ArrayList<FStatement> stmts, Set<FAccessExp> usesLHS, 
2623            Set<FVariable> fvSet, Set<FVariable> fvUse) {
2624       
2625        defSet(fvSet, fvUse);
2626        stmts.add(copySymbolic());
2627    }
2628    public void FIfStmt.addAsInitial(ArrayList<FStatement> stmts, Set<FAccessExp> usesLHS, 
2629            Set<FVariable> fvSet, Set<FVariable> fvUse) {
2630       
2631        if (!isWhen()) {
2632            super.addAsInitial(stmts, usesLHS, fvSet, fvUse);
2633            return;
2634        }
2635       
2636        boolean first = true;
2637        for (FIfWhenClause c : getFIfWhenClauses()) {
2638            if (c.getTest().isInitialGuard() && first) {
2639                for (FStatement s : c.getFStatements()) {
2640                    s.defSet(fvSet, fvUse);
2641                    stmts.add(s.copySymbolic());
2642                }
2643                first = false;
2644            } else {
2645                usesLHS.removeAll(c.findFAccessExpsInTree());
2646            }
2647        }
2648    }
2649   
2650    syn boolean FExp.isInitialGuard() = false;
2651    eq FInitialExp.isInitialGuard() = true;
2652    eq FOrExp.isInitialGuard() = getLeft().isInitialGuard() || getRight().isInitialGuard();
2653           
2654    /**
2655     * Find LHS variables which are definetly assigned to before any use.
2656     */
2657    public Set<FVariable> FAlgorithm.defSet() {
2658        HashSet<FVariable> fvSet = new HashSet<FVariable>();
2659        HashSet<FVariable> fvUse = new HashSet<FVariable>();
2660        for (FStatement stmt : getFStatements()) {
2661            stmt.defSet(fvSet, fvUse);
2662        }
2663        return fvSet;
2664    }
2665    public void FStatement.defSetAdd(Set<FVariable> s1, Set<FVariable> s2, Collection<FVariable> fvs) {
2666        for (FVariable fv : fvs)
2667            if (!s1.contains(fv))
2668                s2.add(fv);
2669    }
2670    public void FStatement.defSet(Set<FVariable> fvSet, Set<FVariable> fvUse) {
2671        defSetAdd(fvSet, fvUse, lookupFVariablesInSet(FAccessExpsInRHS()));
2672    }
2673    public void FAssignStmt.defSet(Set<FVariable> fvSet, Set<FVariable> fvUse) {
2674        defSetAdd(fvSet, fvUse, lookupFVariablesInSet(getRight().findFAccessExpsInTree()));
2675        defSetAdd(fvUse, fvSet, lookupFVariablesInSet(getLeft().findFAccessExpsInTree()));
2676    }
2677    public void FFunctionCallStmt.defSet(Set<FVariable> fvSet, Set<FVariable> fvUse) {
2678        defSetAdd(fvSet, fvUse, lookupFVariablesInSet(getCall().findFAccessExpsInTree()));
2679        for (FFunctionCallLeft left : getLefts())
2680            if (left.hasFExp())
2681                defSetAdd(fvUse, fvSet, lookupFVariablesInSet(left.getFExp().findFAccessExpsInTree()));
2682    }
2683   
2684    /**
2685     * Check if tree contains a function call returning an array or a record.
2686     */
2687    syn boolean ASTNode.hasCompositeFunc() {
2688        for (ASTNode n : this)
2689            if (n.hasCompositeFunc())
2690                return true;
2691        return false;
2692    }
2693    eq InstFunctionCall.hasCompositeFunc() = 
2694        type().isArray() || type().isRecord() || super.hasCompositeFunc();
2695    eq FFunctionCall.hasCompositeFunc()    = 
2696        type().isArray() || type().isRecord() || super.hasCompositeFunc();
2697   
2698    syn boolean FVariable.hasParamValueExp() = hasBindingExp() || startAttributeSet();
2699    syn FExp FVariable.paramValueExp() = hasBindingExp() ? getBindingExp() : startAttributeExp();
2700   
2701    syn boolean FVariable.isVariable() = !isParameter() && !isConstant();
2702   
2703    syn boolean FAbstractVariable.isFVariable() = false;
2704    eq FVariable.isFVariable()                  = true;
2705
2706    syn boolean FAbstractVariable.isFRealVariable() = false;
2707    eq FRealVariable.isFRealVariable()              = true;
2708   
2709    syn boolean FAbstractVariable.isFFunctionVariable() = false;
2710    eq FFunctionVariable.isFFunctionVariable()          = true;
2711
2712    syn boolean FAbstractVariable.isDifferentiatedVariable() = false;
2713    syn lazy boolean FVariable.isDifferentiatedVariable() = zVariability() == FClass.ZVariability.DIFFERENTIATED;
2714    syn boolean FDynamicStateVariable.isDifferentiatedVariable() = true;
2715
2716    syn boolean FAbstractVariable.isAbstractDerivativeVariable() = false;
2717    eq FAbstractDerivativeVariable.isAbstractDerivativeVariable() = true;
2718
2719    syn boolean FAbstractVariable.isDerivativeVariable() = false;
2720    eq FDerivativeVariable.isDerivativeVariable() = true;
2721
2722    syn FVariable FAbstractVariable.asFVariable() {
2723        throw new UnsupportedOperationException("asFVariable() is not supported for class type " + getClass().getSimpleName());
2724    }
2725    eq FVariable.asFVariable() = this;
2726
2727    syn FRealVariable FAbstractVariable.asFRealVariable() {
2728        throw new UnsupportedOperationException("asFRealVariable() is not supported for class type " + getClass().getSimpleName());
2729    }
2730    eq FRealVariable.asFRealVariable() = this;
2731   
2732    syn FDerivativeVariable FAbstractVariable.asDerivativeVariable() {
2733        throw new UnsupportedOperationException("isDerivativeVariable() is not supported for class type " + getClass().getSimpleName());
2734    }
2735    eq FDerivativeVariable.asDerivativeVariable() = this;
2736
2737    syn boolean FAbstractVariable.isDummyDerivativeVariable() = false;
2738    eq FDummyDerivativeVariable.isDummyDerivativeVariable() = true;
2739
2740    syn boolean FAbstractVariable.isNonDummyDerivativeVariable()  = false;
2741    eq FAbstractDerivativeVariable.isNonDummyDerivativeVariable() = true;
2742    eq FDummyDerivativeVariable.isNonDummyDerivativeVariable()    = false;
2743
2744    syn boolean FAbstractVariable.isDynamicDerivativeVariable() = false;
2745    eq FDynamicDerivativeVariable.isDynamicDerivativeVariable() = true;
2746   
2747    syn boolean FAbstractVariable.isPreVariable() = false;
2748    eq FPreRealVariable.isPreVariable() = true;
2749    eq FPreIntegerVariable.isPreVariable() = true;
2750    eq FPreBooleanVariable.isPreVariable() = true;
2751    eq FPreStringVariable.isPreVariable() = true;
2752    eq FPreEnumVariable.isPreVariable() = true;
2753   
2754    syn boolean FAbstractVariable.isAlgebraicVariable() = false;
2755    syn boolean FVariable.isAlgebraicVariable()    = FClass.ALGEBRAIC_FILTER.testSingle(zCategory());
2756
2757    syn boolean FAbstractVariable.isDiscreteVariable() = false;
2758    syn boolean FVariable.isDiscreteVariable()    = zVariability() == FClass.ZVariability.DISCRETE;
2759
2760    syn boolean FAbstractVariable.isAlgebraicContinousRealVariable() = false;
2761    syn boolean FVariable.isAlgebraicContinousRealVariable()    = zCategory() == FClass.ZOrdinaryCategory.CONTINUOUS;
2762
2763    syn GUIDManager FClass.guidManager() = root().getUtilInterface().getGuidManager();
2764
2765    // TODO: This should be handled with a local map when needed, e.g. during
2766    // index reduction!
2767    @Deprecated
2768    private FVariable FVariable.meDifferentiated = null;
2769    @Deprecated
2770    private FVariable FVariable.meIntegrated = null;
2771
2772    @Deprecated
2773    public void FVariable.setMeDifferentiated(FVariable var) {
2774        this.meDifferentiated = var;
2775    }
2776
2777    /**
2778     * This method should only be used during index reduction where we can't
2779     * use variable lookup to resolve higher and lower order variables!
2780     * Instead, please use {@link #myDerivativeVariable()} instead!
2781     */
2782    @Deprecated
2783    public FVariable FVariable.getMeDifferentiated() {
2784        return this.meDifferentiated;
2785    }
2786
2787    @Deprecated
2788    public void FVariable.setMeIntegrated(FVariable var) {
2789        this.meIntegrated = var;
2790    }
2791
2792    /**
2793     * This method should only be used during index reduction where we can't
2794     * use variable lookup to resolve higher and lower order variables!
2795     * Instead, please use {@link #myDifferentiatedVariable()} instead!
2796     */
2797    @Deprecated
2798    public FVariable FVariable.getMeIntegrated() {
2799        return this.meIntegrated;
2800    }
2801
2802    @Deprecated
2803    public FVariable FVariable.getTopIntegrated() {
2804        FVariable fv = this;
2805        while (fv.meIntegrated != null)
2806            fv = fv.meIntegrated;
2807        return fv;
2808    }
2809
2810    // TODO: Unlike higher and lower order function on variables, this one
2811    // actually doesn't have any corresponding constructions, so we might
2812    // actually wan't to keep this functionality. However we should probably
2813    // move it to tokens or similar.
2814    @Deprecated
2815    private FAbstractEquation FAbstractEquation.meDifferentiated = null;
2816
2817    @Deprecated
2818    private FAbstractEquation FAbstractEquation.meIntegrated = null;
2819
2820    @Deprecated
2821    public void FAbstractEquation.setMeDifferentiated(FAbstractEquation e) {
2822        this.meDifferentiated = e;
2823    }
2824
2825    @Deprecated
2826    public FAbstractEquation FAbstractEquation.getMeDifferentiated() {
2827        return this.meDifferentiated;
2828    }
2829
2830    @Deprecated
2831    public void FAbstractEquation.setMeIntegrated(FAbstractEquation e) {
2832        this.meIntegrated = e;
2833    }
2834
2835    @Deprecated
2836    public FAbstractEquation FAbstractEquation.getMeIntegrated() {
2837        return this.meIntegrated;
2838    }
2839}
2840
2841aspect ReferencedVariables {
2842   
2843    public interface CommonAccessExpLookupVisitor<T extends CommonAccessExp> {
2844        public void visit(ASTNode<? extends ASTNode> node, Set<T> set);
2845        public abstract void add(CommonAccessExp access, Set<T> set);
2846    }
2847   
2848    public abstract class InstAccessExpLookupVisitor implements CommonAccessExpLookupVisitor<InstAccessExp> {
2849        @Override
2850        public void add(CommonAccessExp access, Set<InstAccessExp> set) {
2851            access.addToInstAccessExpSet(set);
2852        }
2853    }
2854
2855    public abstract class FAccessExpLookupVisitor implements CommonAccessExpLookupVisitor<FAccessExp> {
2856        @Override
2857        public void add(CommonAccessExp access, Set<FAccessExp> set) {
2858            access.addToFAccessExpSet(set);
2859        }
2860    }
2861
2862    public class DefaultInstAccessExpLookupVisitor extends InstAccessExpLookupVisitor {
2863        public static final DefaultInstAccessExpLookupVisitor instance = new DefaultInstAccessExpLookupVisitor();
2864       
2865        @Override
2866        public void visit(ASTNode<? extends ASTNode> node, Set<InstAccessExp> set) {
2867            node.findCommonAccessExpsInTree(set, this);
2868        }
2869    }
2870   
2871    public class DefaultFAccessExpLookupVisitor extends FAccessExpLookupVisitor {
2872        public static final DefaultFAccessExpLookupVisitor instance = new DefaultFAccessExpLookupVisitor();
2873       
2874        @Override
2875        public void visit(ASTNode<? extends ASTNode> node, Set<FAccessExp> set) {
2876            node.findCommonAccessExpsInTree(set, this);
2877        }
2878    }
2879   
2880    public void CommonAccessExp.addToInstAccessExpSet(Set<InstAccessExp> set) {}
2881    public void InstAccessExp.addToInstAccessExpSet(Set<InstAccessExp> set) {
2882        set.add(this);
2883    }
2884
2885    public void CommonAccessExp.addToFAccessExpSet(Set<FAccessExp> set) {}
2886    public void FAccessExp.addToFAccessExpSet(Set<FAccessExp> set) {
2887        set.add(this);
2888    }
2889
2890    public Set<InstAccessExp> ASTNode.findInstAccessExpsInTree() {
2891        return findCommonAccessExpsInTree(DefaultInstAccessExpLookupVisitor.instance);
2892    }
2893
2894    public Set<FAccessExp> ASTNode.findFAccessExpsInTree() {
2895        return findCommonAccessExpsInTree(DefaultFAccessExpLookupVisitor.instance);
2896    }
2897   
2898    public <T extends CommonAccessExp> Set<T> ASTNode.findCommonAccessExpsInTree(CommonAccessExpLookupVisitor<T> visitor) {
2899        Set<T> set = new LinkedHashSet<>();
2900        visitor.visit(this, set);
2901        return set;
2902    }
2903   
2904    public <T extends CommonAccessExp> void ASTNode.findCommonAccessExpsInTree(Set<T> set, CommonAccessExpLookupVisitor<T> visitor) {
2905        for (ASTNode n : this) {
2906            visitor.visit(n, set);
2907        }
2908    }
2909
2910    @Override
2911    public <T extends CommonAccessExp> void CommonAccessExp.findCommonAccessExpsInTree(Set<T> set, CommonAccessExpLookupVisitor<T> visitor) {
2912        visitor.add(this, set);
2913        super.findCommonAccessExpsInTree(set, visitor);
2914    }
2915
2916    @Override
2917    public <T extends CommonAccessExp> void FRelExp.findCommonAccessExpsInTree(Set<T> set, CommonAccessExpLookupVisitor<T> visitor) {
2918        if (!hasIndicator()) {
2919            super.findCommonAccessExpsInTree(set, visitor);
2920        } else {
2921            for (ASTNode<?> n : this) {
2922                if (n != getIndicatorOpt()) {
2923                    n.findCommonAccessExpsInTree(set, visitor);
2924                }
2925            }
2926        }
2927    }
2928
2929    @Override
2930    public <T extends CommonAccessExp> void FAttribute.findCommonAccessExpsInTree(Set<T> set, CommonAccessExpLookupVisitor<T> visitor) {
2931    }
2932
2933    syn Set<FAccessExp> FAbstractEquation.FAccessExpsInRHS() = FAccessExpsInRHS(DefaultFAccessExpLookupVisitor.instance);
2934
2935    syn Set<FAccessExp> FAbstractEquation.FAccessExpsInRHS(CommonAccessExpLookupVisitor<FAccessExp> visitor)
2936        = Collections.emptySet();
2937    eq FEquation.FAccessExpsInRHS(CommonAccessExpLookupVisitor<FAccessExp> visitor)
2938        = getRight().findCommonAccessExpsInTree(visitor);
2939    eq FFunctionCallEquation.FAccessExpsInRHS(CommonAccessExpLookupVisitor<FAccessExp> visitor)
2940        = getCall().findCommonAccessExpsInTree(visitor);
2941    eq FAlgorithm.FAccessExpsInRHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
2942        Set<FAccessExp> res = new LinkedHashSet<FAccessExp>();
2943        for (FStatement stmt : getFStatements())
2944            res.addAll(stmt.FAccessExpsInRHS(visitor));
2945        return res;
2946    }
2947
2948    syn Set<FAccessExp> FStatement.FAccessExpsInRHS() = FAccessExpsInRHS(DefaultFAccessExpLookupVisitor.instance);
2949
2950    syn Set<FAccessExp> FStatement.FAccessExpsInRHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
2951        Set<FAccessExp> res = new LinkedHashSet<>();
2952        for (FAccessExp use : findCommonAccessExpsInTree(visitor))
2953            if (!use.useIsAssignment() && !use.myFV().isForIndex())
2954                res.add(use);
2955        res.removeAll(FAccessExpsInLHS(visitor));
2956        return res;
2957    }
2958   
2959    eq FIfWhenElseEquation.FAccessExpsInRHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
2960        Set<FAccessExp> res = new LinkedHashSet<FAccessExp>();
2961        for (FAbstractEquation fae : getFAbstractEquations())
2962            res.addAll(fae.FAccessExpsInRHS(visitor));
2963        return res;
2964    }
2965   
2966    eq FIfWhenEquation.FAccessExpsInRHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
2967        Set<FAccessExp> res = super.FAccessExpsInRHS(visitor);
2968        getTest().findCommonAccessExpsInTree(res, visitor);
2969        if (hasElse())
2970            res.addAll(getElse().FAccessExpsInRHS(visitor));
2971        return res;
2972    }
2973   
2974    syn Set<FAccessExp> FAbstractEquation.FAccessExpsInLHS() = FAccessExpsInLHS(DefaultFAccessExpLookupVisitor.instance);
2975   
2976    syn Set<FAccessExp> FAbstractEquation.FAccessExpsInLHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) = Collections.emptySet();
2977    eq FEquation.FAccessExpsInLHS(CommonAccessExpLookupVisitor<FAccessExp> visitor)             = getLeft().findCommonAccessExpsInTree(visitor);
2978    eq FFunctionCallEquation.FAccessExpsInLHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) = getLefts().findCommonAccessExpsInTree(visitor);
2979    eq FAlgorithm.FAccessExpsInLHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
2980        Set<FAccessExp> res = new LinkedHashSet<FAccessExp>();
2981        for (FStatement stmt : getFStatements())
2982            res.addAll(stmt.FAccessExpsInLHS(visitor));
2983        return res;
2984    }
2985   
2986    syn Set<FAccessExp> FStatement.FAccessExpsInLHS() = FAccessExpsInLHS(DefaultFAccessExpLookupVisitor.instance);
2987   
2988    syn Set<FAccessExp> FStatement.FAccessExpsInLHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
2989        Set<FAccessExp> res = new LinkedHashSet<>();
2990        for (FAccessExp use : findCommonAccessExpsInTree(visitor))
2991            if (use.useIsAssignment() && !use.myFV().isForIndex())
2992                res.add(use);
2993        return res;
2994    }
2995   
2996    eq FIfWhenElseEquation.FAccessExpsInLHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
2997        Set<FAccessExp> res = new LinkedHashSet<FAccessExp>();
2998        for (FAbstractEquation fae : getFAbstractEquations())
2999            res.addAll(fae.FAccessExpsInLHS(visitor));
3000        return res;
3001    }
3002   
3003    eq FIfWhenEquation.FAccessExpsInLHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
3004        Set<FAccessExp> res = super.FAccessExpsInLHS(visitor);
3005        if (hasElse())
3006            res.addAll(getElse().FAccessExpsInLHS(visitor));
3007        return res;
3008    }
3009   
3010    syn ArrayList<FAccessExp> FAbstractEquation.uniqueFAccessExpsInLHS() {
3011        ArrayList<FAccessExp>   res   = new ArrayList<>();
3012        Set<FAbstractVariable> visit = new LinkedHashSet<FAbstractVariable>();
3013        for (FAccessExp e : FAccessExpsInLHS()) {
3014            FAbstractVariable fv = e.myFV();
3015            if (!visit.contains(fv)) {
3016                visit.add(fv);
3017                res.add(e);
3018            }
3019        }
3020        return res;
3021    }
3022
3023    syn lazy Set<FAccessExp> FAbstractEquation.referencedCommonAccessExps() {
3024        Set<FAccessExp> res = new LinkedHashSet<>();
3025        res.addAll(FAccessExpsInLHS());
3026        res.addAll(FAccessExpsInRHS());
3027        return res;
3028    }
3029
3030    /***
3031     * DANGER! Use this method and its results with caution. It will probably
3032     * not work before saclarization but should be safe afterwards!
3033     */
3034    syn Set<String> FAbstractEquation.referencedVariablesAsStrings() {
3035        Set<FAccessExp> exps = new LinkedHashSet<FAccessExp>();
3036        Set<String> res = new LinkedHashSet<String>();
3037        for (FAccessExp exp : exps) {
3038            res.add(exp.name());
3039        }
3040        return res;
3041    }
3042    public static Set<FVariable> ASTNode.lookupFVariablesInSet(Set<FAccessExp> set) {
3043        Set<FVariable> res = new LinkedHashSet<FVariable>();
3044        for (FAccessExp use : set)
3045            if (use.myFV() instanceof FVariable)
3046                res.add((FVariable) use.myFV());
3047        return res;
3048    }
3049
3050    syn Set<FVariable> FAbstractEquation.variableDependenciesRHS() = referencedFVariablesInRHS();
3051    eq FAlgorithm.variableDependenciesRHS() {
3052        Set<FVariable> lhs = referencedFVariablesInLHS();
3053        Set<FVariable> rhs = referencedFVariablesInRHS();
3054        Set<FVariable> res = new LinkedHashSet<FVariable>();
3055        for (FVariable fv : rhs) {
3056            if (!lhs.contains(fv)) {
3057                res.add(fv);
3058            }
3059        }
3060        return res;
3061    }
3062   
3063    syn Set<FVariable> FAbstractEquation.referencedFVariablesInRHS() = lookupFVariablesInSet(FAccessExpsInRHS());
3064    syn Set<FVariable> FAbstractEquation.referencedFVariablesInLHS() = lookupFVariablesInSet(FAccessExpsInLHS());
3065    // Lazy is needed for FAlgorithms since the can have large number of scalars
3066    syn lazy Set<FVariable> FAlgorithm.referencedFVariablesInLHS() = super.referencedFVariablesInLHS();
3067    syn Set<FVariable> FExp.referencedFVariablesInFExp()             = lookupFVariablesInSet(findFAccessExpsInTree());
3068    syn Set<FVariable> FVariable.referencedFVariablesInBindingExp()  = lookupFVariablesInSet(getBindingExp().findFAccessExpsInTree());
3069    syn lazy Set<FVariable> FAbstractEquation.referencedFVariables() = lookupFVariablesInSet(referencedCommonAccessExps());
3070
3071    public static Set<FVariable> ASTNode.parametersInSet(Set<? extends FVariable> set) {
3072        Set<FVariable> res = new LinkedHashSet<FVariable>();
3073        for (FVariable fv : set)
3074            if (fv.isParameter())
3075                res.add(fv);
3076        return res;
3077    }
3078   
3079    syn Set<FVariable> FFunctionCallEquation.referencedParametersInLHS() = parametersInSet(referencedFVariablesInLHS());
3080    syn Set<FVariable> FExp.referencedParametersInFExp()                 = parametersInSet(referencedFVariablesInFExp());
3081
3082    syn boolean FAbstractEquation.assignedInAllBranches(FAbstractVariable var) = true;
3083    eq FEquation.assignedInAllBranches(FAbstractVariable var) = assignedInAllBranchesVariables().contains(var.name());
3084
3085    syn lazy Set<String> FEquation.assignedInAllBranchesVariables() {
3086        Set<String> res = new HashSet<String>();
3087        getLeft().assignedInAllBranchesVariables(res);
3088        getRight().assignedInAllBranchesVariables(res);
3089        return res;
3090    }
3091
3092    public final Set<String> FExp.assignedInAllBranchesVariables() {
3093        Set<String> res = new HashSet<String>();
3094        assignedInAllBranchesVariables(res);
3095        return res;
3096    }
3097
3098    public void FExp.assignedInAllBranchesVariables(Set<String> res) {
3099        for (FExp exp : childFExps())
3100            exp.assignedInAllBranchesVariables(res);
3101    }
3102
3103    @Override
3104    public void FAccessExp.assignedInAllBranchesVariables(Set<String> res) {
3105        res.add(name());
3106    }
3107
3108    @Override
3109    public void FIfExp.assignedInAllBranchesVariables(Set<String> res) {
3110        getIfExp().assignedInAllBranchesVariables(res);
3111        Set<String> a = getThenExp().assignedInAllBranchesVariables();
3112        Set<String> b = getElseExp().assignedInAllBranchesVariables();
3113        if (a.size() > b.size()) {
3114            Set<String> tmp = a;
3115            a = b;
3116            b = tmp;
3117        }
3118        for (String name : a) {
3119            if (b.contains(name)) {
3120                res.add(name);
3121            }
3122        }
3123    }
3124}
3125
3126
3127aspect FlatEnumerations {
3128   
3129    public ArrayList<FEnumLiteral> FEnumDecl.enumLiterals() {
3130        return getFEnumSpecification().enumLiterals();
3131    }
3132
3133    public ArrayList<FEnumLiteral> FEnumSpecification.enumLiterals() {
3134        return new ArrayList<FEnumLiteral>();
3135    }
3136
3137    public ArrayList<FEnumLiteral> FEnumLiteralList.enumLiterals() {
3138        ArrayList<FEnumLiteral> l = new ArrayList<FEnumLiteral>();
3139        for (FEnumLiteral el : getFEnumLiterals()) {
3140            l.add(el);
3141        }
3142        return l;
3143    }
3144   
3145    /**
3146     * The number of enumeration literals defined in the enumeration this variable is of.
3147     */
3148    syn int FEnumVariable.numEnumLiterals() = myFEnumDecl().numEnumLiterals();
3149   
3150    /**
3151     * The number of enumeration literals defined in this enumeration.
3152     */
3153    syn int FEnumDecl.numEnumLiterals() = getFEnumSpecification().numEnumLiterals();
3154   
3155    /**
3156     * The number of enumeration literals defined in this enumeration.
3157     */
3158    syn int FEnumSpecification.numEnumLiterals() = 0;
3159    eq FEnumLiteralList.numEnumLiterals() = getNumFEnumLiteral();
3160   
3161}
3162
3163aspect FlatCausality {
3164   
3165    syn boolean FAbstractVariable.isInput() = false;
3166    syn boolean FAbstractVariable.isOutput() = false;
3167    eq FVariable.isInput()          = getCausalityConnectorPrefix().inputCausality (this);
3168    eq FVariable.isOutput()         = getCausalityConnectorPrefix().outputCausality(this);
3169    eq FFunctionVariable.isInput()  = getCausalityConnectorPrefix().inputCausality (this);
3170    eq FFunctionVariable.isOutput() = getCausalityConnectorPrefix().outputCausality(this);
3171   
3172    ASTNode implements CausalPortsEvaluator;
3173    syn boolean ASTNode.useCausalPorts() = myOptions().causal_ports.getValue();
3174}
3175
3176aspect FlatTypes {
3177
3178    syn boolean FAbstractVariable.isReal()              = type().isReal();
3179    syn boolean FAbstractVariable.isInteger()           = type().isInteger();
3180    syn boolean FAbstractVariable.isBoolean()           = type().isBoolean();
3181    syn boolean FAbstractVariable.isString()            = type().isString();
3182    syn boolean FAbstractVariable.isRecord()            = type().isRecord();
3183    syn boolean FAbstractVariable.isEnum()              = type().isEnum();
3184    syn boolean FAbstractVariable.isExternalObject()    = type().isExternalObject();
3185   
3186    syn boolean FExp.isComposite()              = isArray() || type().isRecord();
3187    syn boolean FType.isComposite()             = isArray() || isRecord();
3188    syn boolean FAbstractVariable.isComposite() = isArray() || isRecord();
3189    syn boolean InstComponentDecl.isComposite() = isArray() || isRecord();
3190   
3191    inh boolean FAbstractVariable.inRecord();
3192    eq FRecordDecl.getChild().inRecord() = true;
3193    eq FClass.getChild().inRecord()      = false;
3194    eq FForIndex.getChild().inRecord()   = false;
3195
3196    inh boolean InstNode.inRecord();
3197    eq Root.getChild().inRecord()                               = false;
3198    eq InstClassDecl.getChild().inRecord()                      = false;
3199    eq InstForIndex.getInstPrimitive().inRecord()               = false;
3200    eq InstRecord.getChild().inRecord()                         = true;
3201    eq InstRecordConstructor.getChild().inRecord()              = true;
3202    eq InstArrayComponentDecl.getInstComponentDecl().inRecord() = inRecord();
3203    eq InstExtends.getInstComponentDecl().inRecord()            = inRecord();
3204
3205    inh boolean InstNode.inRecordDecl();
3206    eq Root.getChild().inRecordDecl()           = false;
3207    eq InstClassDecl.getChild().inRecordDecl()  = isRecord();
3208
3209    inh boolean InstComponentDecl.inRecordConstructor();
3210    inh boolean InstExtends.inRecordConstructor();
3211    eq InstRecordConstructor.getInstComponentDecl().inRecordConstructor() = true;
3212    eq InstRecordConstructor.getInstExtends().inRecordConstructor()       = true;
3213    eq InstExtends.getChild().inRecordConstructor()                       = inRecordConstructor();
3214    eq InstNode.getChild().inRecordConstructor()                          = false;
3215    eq Root.getChild().inRecordConstructor()                              = false;
3216
3217    syn int FRecordDecl.indexOf(String name) {
3218        for (int i = 0; i < getNumFVariable(); i++)
3219            if (getFVariable(i).name().equals(name))
3220                return i;
3221        return -1;
3222    }
3223   
3224    syn int FRecordDecl.indexOfArg(String name) {
3225        int k = 0;
3226        for (int i = 0; i < getNumFVariable(); i++) {
3227            if (getFVariable(i).modifiableInRecord) {
3228                if (getFVariable(i).name().equals(name))
3229                    return k;
3230                k++;
3231            }
3232        }
3233        return -1;
3234    }
3235   
3236    syn FExp FRecordDecl.extractArg(FRecordConstructor frc, String name) {
3237        return frc.getArg(indexOf(name));
3238    }
3239   
3240    inh FRecordDecl FExp.containingRecordDecl();
3241    inh FRecordDecl FAbstractVariable.containingRecordDecl();
3242    eq FRecordDecl.getChild().containingRecordDecl() = this;
3243    eq Root.getChild().containingRecordDecl()        = null;
3244
3245}
3246
3247
3248aspect Nominals {
3249    syn FExp FAbstractEquation.nominal() {
3250        FExp nom = FExp.nominalDefault();
3251        nom.setParent(this);
3252        return nom;
3253    }
3254    eq FEquation.nominal() {
3255        FExp nom = getLeft().dynamicFExp(FExp.nominalMax(getLeft(), getRight()));
3256        if (nom.variability().knownParameterOrLess()) {
3257            try {
3258                CValue val = nom.ceval();
3259                if (val.hasBuildLiteral()) {
3260                    nom = getLeft().dynamicFExp(val.buildLiteral());
3261                }
3262            } catch (ConstantEvaluationException e) {}
3263        }
3264        return nom;
3265    }
3266   
3267    public static FExp FExp.nominalMax(FExp e1, FExp e2) {
3268        return new FMaxExp(e1.nominal(), new Opt<FExp>(e2.nominal()));
3269    }
3270    public static FExp FExp.nominalDefault() {
3271        return new FIntegerLitExp(1);
3272    }
3273   
3274    syn FExp FExp.nominal() = FExp.nominalDefault();
3275    eq FLitExp.nominal()    = new FAbsExp(fullCopy());
3276   
3277    eq FDotAddExp.nominal() = FExp.nominalMax(getLeft(), getRight());
3278    eq FDotSubExp.nominal() = FExp.nominalMax(getLeft(), getRight());
3279    eq FDotMulExp.nominal() = new FMulExp(getLeft().nominal(), getRight().nominal());
3280    eq FDotDivExp.nominal() = new FDivExp(getLeft().nominal(), getRight().nominal());
3281    eq FNegExp.nominal()    = getFExp().nominal();
3282    eq FAbsExp.nominal()    = getFExp().nominal();
3283    eq FMinMaxExp.nominal() = hasY() ? FExp.nominalMax(getX(), getY()) : getX().nominal();
3284   
3285    eq FIfExp.nominal()     = FExp.nominalMax(getThenExp(), getElseExp());
3286   
3287    eq FNoEventExp.nominal() = getFExp().nominal();
3288    eq FSmoothExp.nominal()  = getFExp().nominal();
3289   
3290    eq FHomotopyExp.nominal()    = FExp.nominalMax(getActual(), getSimplified());
3291    eq FSpatialDistExp.nominal() = FExp.nominalMax(getIn0(), getIn1());
3292    eq FDelayExp.nominal()       = getFExp().nominal();
3293   
3294    eq FAccessExp.nominal() = myFV().nominal();
3295    eq FGlobalAccessExp.nominal() = new FAbsExp(treeCopy());
3296   
3297    syn FExp FAbstractVariable.nominal() {
3298        if (variability().fixedParameterOrLess()) {
3299            return new FAbsExp(createAccessExp());
3300        } else {
3301            return variableNominal();
3302        }
3303    }
3304    eq UnknownFVariable.nominal() = variableNominal();
3305   
3306    syn FExp FAbstractVariable.variableNominal() {
3307        return FExp.nominalDefault();
3308    }
3309   
3310    eq FRealVariable.variableNominal() {
3311        if (nominalAttributeSet()) {
3312            return new FAbsExp(nominalAttributeExp().unboundCopy());
3313        } else {
3314            return super.variableNominal();
3315        }
3316    }
3317}
3318
3319aspect FVariableUses {
3320   
3321    /**
3322     * Collection attribute returning all variable uses in expressions.
3323     */
3324    coll HashSet<FAccessExp> FAbstractVariable.uses() [new LinkedHashSet<>()] 
3325        with add root FClass;
3326   
3327    FAccessExp contributes this to FAbstractVariable.uses() for myFV();
3328   
3329    /**
3330     * All uses of this variable that are not the left-hand side of an equation.
3331     * (Unless the variable has a binding expression, then this is the same as uses().)
3332     */
3333    syn lazy Set<FAccessExp> FAbstractVariable.nonDefiningUses() {
3334        Set<FAccessExp> res = new HashSet<FAccessExp>();
3335        for (FAccessExp use : uses())
3336            if (hasBindingExp() || !use.isLeftHandSide())
3337                res.add(use);
3338        return res;
3339    }
3340   
3341    /**
3342     * All uses of this variable that are the left-hand side of an equation.
3343     * (Unless the variable has a binding expression, then this is empty.)
3344     */
3345    syn lazy Set<FAccessExp> FAbstractVariable.definingUses() {
3346        if (hasBindingExp()) {
3347            return Collections.emptySet();
3348        } else {
3349            Set<FAccessExp> res = new HashSet<FAccessExp>();
3350            for (FAccessExp use : uses())
3351                if (use.isLeftHandSide())
3352                    res.add(use);
3353            return res;
3354        }
3355    }
3356   
3357    inh boolean FExp.inFunctionCallLeft();
3358    eq FFunctionCallLeft.getChild().inFunctionCallLeft() = true;
3359    eq FClass.getChild().inFunctionCallLeft()            = false;
3360    eq InstRoot.getChild().inFunctionCallLeft()          = false;
3361   
3362    inh boolean FExp.isFunctionCallLeft();
3363    eq FFunctionCallLeft.getChild().isFunctionCallLeft() = true;
3364    eq FExp.getChild().isFunctionCallLeft()              = false;
3365    eq FClass.getChild().isFunctionCallLeft()            = false;
3366    eq InstRoot.getChild().isFunctionCallLeft()          = false;
3367   
3368    /**
3369     * Checks if this expression is used in a function call
3370     */
3371    inh boolean FExp.inFunctionCall();
3372    eq FFunctionCall.getChild().inFunctionCall() = true;
3373    eq FClass.getChild().inFunctionCall()        = false;
3374    eq InstRoot.getChild().inFunctionCall()      = false;
3375   
3376    inh boolean FExp.isFunctionCallArg();
3377    eq BaseNode.getChild().isFunctionCallArg()    = false;
3378    eq FFunctionCall.getArg().isFunctionCallArg() = true;
3379    eq FIfExp.getThenExp().isFunctionCallArg()    = isFunctionCallArg();
3380    eq FIfExp.getElseExp().isFunctionCallArg()    = isFunctionCallArg();
3381
3382    syn boolean FExp.containsCommonFunctionCallExp() {
3383        for (FExp exp : childFExps()) {
3384            if (exp.containsCommonFunctionCallExp()) {
3385                return true;
3386            }
3387        }
3388        return false;
3389    }
3390    eq CommonFunctionCall.containsCommonFunctionCallExp() = true;
3391
3392    /**
3393     * Returnes the function input that this expressions corresponds to.
3394     * NOTICE, this method will throw exception if this exp does not reside in a function call.
3395     */
3396    inh CommonVariableDecl FExp.myCorrespondingInput();
3397    eq FFunctionCall.getArg(int i).myCorrespondingInput()    = myFCallable().myInput(i);
3398    eq InstFunctionCall.getArg(int i).myCorrespondingInput() = myInstCallable().myCallInputs().get(i);
3399    eq FClass.getChild().myCorrespondingInput() {
3400        throw new UnsupportedOperationException();
3401    }
3402    eq InstRoot.getChild().myCorrespondingInput() {
3403        throw new UnsupportedOperationException();
3404    }
3405   
3406    /**
3407     * Check if this is the left hand side of an equation.
3408     */
3409    inh boolean FExp.isLeftHandSide();
3410    eq BaseNode.getChild().isLeftHandSide()    = false;
3411    eq FEquation.getLeft().isLeftHandSide()    = true;
3412    eq FFunctionCallLeft.getChild().isLeftHandSide()  = true;
3413    eq FArray.getChild().isLeftHandSide()             = isLeftHandSide();
3414    eq FRecordConstructor.getChild().isLeftHandSide() = isLeftHandSide();
3415   
3416    /**
3417     * Check if this is the left hand side of an assignment or function call statement.
3418     */
3419    inh boolean FAssignableExp.isAssignedTo();
3420    inh boolean FFunctionCallLeft.isAssignedTo();
3421    eq BaseNode.getChild().isAssignedTo()         = false;
3422    eq FAssignStmt.getLeft().isAssignedTo()       = true;
3423    eq FFunctionCallStmt.getLeft().isAssignedTo() = true;
3424    eq FFunctionCallLeft.getFExp().isAssignedTo() = isAssignedTo();
3425   
3426    /**
3427     * Check if this is exp is bound in a declaration
3428     */
3429    inh boolean FExp.isBound();
3430    eq Root.getChild().isBound()                   = false;
3431    eq InstValueModification.getFExp().isBound()   = true;
3432    eq InstFunctionCall.getArg().isBound()        = false;
3433   
3434    inh boolean FExp.inParamBindingExp();
3435    eq Root.getChild().inParamBindingExp() = false;
3436    eq FVariable.getBindingExp().inParamBindingExp() = isParameter();
3437   
3438    inh TypePrefixVariability FExp.bindingExpVariability();
3439    eq Root.getChild().bindingExpVariability() = Variability.CONTINUOUS;
3440    eq FVariable.getChild().bindingExpVariability() = variability();
3441    eq FVariable.getFAttribute().bindingExpVariability() = Variability.FIXEDPARAMETER;
3442    eq FRecordVariable.getFAttribute(int i).bindingExpVariability() =
3443            variability().component(getFAttribute(i).name());
3444   
3445    /**
3446     * Collection attribute returning all dependent parameters which
3447     * depends on the parameter.
3448     */
3449   
3450    coll HashSet<FVariable> FAbstractVariable.dependentParameters() 
3451      [new LinkedHashSet<FVariable>()] 
3452        with addAll root FlatRoot;
3453   
3454    FAccessExp contributes boundParameters() when myFV().isParameter()
3455        to FAbstractVariable.dependentParameters() for myFV();
3456   
3457    syn lazy Collection<FRealVariable> FAbstractVariable.dependentRealParameters() =
3458            FClass.filterCollection(dependentParameters(), FClass.REAL_VARIABLE_FILTER);
3459
3460    syn lazy Collection<FIntegerVariable> FAbstractVariable.dependentIntegerParameters() =
3461            FClass.filterCollection(dependentParameters(), FClass.INTEGER_VARIABLE_FILTER);
3462
3463    syn lazy Collection<FEnumVariable> FAbstractVariable.dependentEnumParameters() =
3464            FClass.filterCollection(dependentParameters(), FClass.ENUM_VARIABLE_FILTER);
3465   
3466    syn lazy Collection<FBooleanVariable> FAbstractVariable.dependentBooleanParameters() =
3467            FClass.filterCollection(dependentParameters(), FClass.BOOLEAN_VARIABLE_FILTER);
3468
3469    syn lazy Collection<FStringVariable> FAbstractVariable.dependentStringParameters() =
3470            FClass.filterCollection(dependentParameters(), FClass.STRING_VARIABLE_FILTER);
3471
3472    /**
3473     * Collection attribute returning all input variables (FVariables)
3474     * referenced in an equation.
3475     */
3476     
3477    coll LinkedHashSet<FVariable> FAbstractEquation.retrieveInputs() 
3478        [new LinkedHashSet<FVariable>()] with add root FAbstractEquation;
3479
3480    FAccessExp contributes (FVariable) myFV() when
3481        myFV().isFVariable() && myFV().isInput() to
3482        FAbstractEquation.retrieveInputs() for myFEquation();
3483
3484    syn lazy LinkedHashSet<FVariable> FAbstractEquation.inputs() = 
3485        retrieveInputs();
3486   
3487    eq FIfWhenElseEquation.inputs()  {
3488        LinkedHashSet<FVariable> s = new LinkedHashSet<FVariable>();
3489        s.addAll(retrieveInputs());
3490        for (FAbstractEquation e : getFAbstractEquations()) {
3491            s.addAll(e.inputs());
3492        }
3493        return s;
3494    }
3495    eq FIfWhenEquation.inputs()  {
3496        LinkedHashSet<FVariable> s = new LinkedHashSet<FVariable>();
3497        s.addAll(super.inputs());
3498        if (hasElse())
3499            s.addAll(getElse().inputs());
3500        return s;
3501    }
3502
3503    syn lazy LinkedHashSet<FVariable> FAbstractEquation.realInputs() = 
3504            new LinkedHashSet<FVariable>(FClass.filterCollection(inputs(), FClass.REAL_VARIABLE_FILTER));
3505
3506   
3507    /**
3508     * Collection attribute returning all algebraic variables (FVariables)
3509     * referenced in an equation.
3510     */
3511    coll LinkedHashSet<FVariable> FAbstractEquation.algebraicVariables() 
3512        [new LinkedHashSet<FVariable>()] with add root FAbstractEquation;
3513
3514    FAccessExp contributes (FVariable) myFV() when isAlgebraicVariableAccess() to
3515        FAbstractEquation.algebraicVariables() for each enclosingEquationsIterator();
3516
3517    syn boolean FAccessExp.isAlgebraicVariableAccess() = inAccessLocation() && myFV().isAlgebraicVariable();
3518
3519    /**
3520     * Returns true if this access is in a location where it should be
3521     * contributed to the equation system.
3522     */
3523    inh boolean FAccessExp.inAccessLocation();
3524    eq FlatRoot.getChild().inAccessLocation()               = false;
3525    eq SourceRoot.getChild().inAccessLocation()             = false;
3526    eq FAbstractEquation.getFAttribute().inAccessLocation() = false;
3527    eq FAbstractEquation.getChild().inAccessLocation()      = true;
3528    eq FRelExp.getIndicator().inAccessLocation()            = false;
3529
3530
3531    /**
3532     * Collection attribute returning all derivative variables (FDerivativeVariables)
3533     * referenced in an equation.
3534     */
3535    coll LinkedHashSet<FDerivativeVariable> FAbstractEquation.derivativeVariables() 
3536        [new LinkedHashSet<FDerivativeVariable>()] with add root FAbstractEquation;
3537
3538    FDerExp contributes (FDerivativeVariable) myFV() when myFV().isDerivativeVariable() && inAccessLocation() to
3539        FAbstractEquation.derivativeVariables() for each enclosingEquationsIterator();
3540
3541    /**
3542     * Collection attribute returning all differentiated variables (FVariables)
3543     * referenced in an equation.
3544     */
3545    coll LinkedHashSet<FVariable> FAbstractEquation.differentiatedRealVariables() 
3546        [new LinkedHashSet<FVariable>()] with add root FAbstractEquation;
3547
3548    FAccessExp contributes (FVariable) myFV() when myFV().isDifferentiatedVariable() && inAccessLocation() to
3549        FAbstractEquation.differentiatedRealVariables() for each enclosingEquationsIterator();
3550
3551    /**
3552     * Collection attribute returning all dependent parameter variables (FVariables)
3553     * referenced in an equation.
3554     */
3555    coll LinkedHashSet<FVariable> FAbstractEquation.parameters() 
3556        [new LinkedHashSet<FVariable>()] with add root FAbstractEquation;
3557
3558    FAccessExp contributes (FVariable) myFV() when myFV().isParameter() && inAccessLocation() to
3559        FAbstractEquation.parameters() for each enclosingEquationsIterator();
3560
3561    /**
3562     * Collection attribute returning all discrete variables (FVariables)
3563     * referenced in an equation.
3564     */
3565    coll LinkedHashSet<FVariable> FAbstractEquation.discreteVariables() 
3566        [new LinkedHashSet<FVariable>()] with add root FAbstractEquation;
3567
3568    FAccessExp contributes (FVariable) myFV() when myFV().isDiscreteVariable() && inAccessLocation() to
3569        FAbstractEquation.discreteVariables() for each enclosingEquationsIterator();
3570
3571    /**
3572     * Collection attribute returning all non-fixed parameters (FVariables)
3573     * referenced in an equation.
3574     */
3575    coll LinkedHashSet<FVariable> FAbstractEquation.initialParameters()
3576        [new LinkedHashSet<FVariable>()] with add root FAbstractEquation;
3577
3578    FAccessExp contributes (FVariable) myFV() when myFV().isInitialParameter() && inAccessLocation() to
3579        FAbstractEquation.initialParameters() for each enclosingEquationsIterator();
3580
3581    /**
3582     * Collection attribute returning all pre variables (FPreVariable)
3583     * referenced in an equation.
3584     */
3585    coll LinkedHashSet<FVariable> FAbstractEquation.discretePreVariables() 
3586        [new LinkedHashSet<FVariable>()] with add root FAbstractEquation;
3587
3588    FPreExp contributes (FVariable) myFV() when myFV().isPreVariable() && inAccessLocation() to
3589        FAbstractEquation.discretePreVariables() for each enclosingEquationsIterator();
3590
3591    syn lazy LinkedHashSet<FVariable> FAbstractEquation.variables() {
3592        LinkedHashSet<FVariable> l = new LinkedHashSet<FVariable>();
3593        l.addAll(differentiatedRealVariables());
3594        l.addAll(derivativeVariables());
3595        l.addAll(algebraicVariables());
3596        l.addAll(discreteVariables());
3597        return l;
3598    }
3599
3600    /**
3601     * Returns the event indicators for the expressions that are found by {@link #relExpInEquation}.
3602     */
3603    syn Set<FVariable> FAbstractEquation.eventIndicators() {
3604        Set<EventGeneratingExp> exps = new HashSet<>();
3605        exps.addAll(relExpInEquation());
3606        exps.addAll(delayExpInEquation());
3607        exps.addAll(spatialDistExpInEquation());
3608       
3609        Set<FVariable> res = new HashSet<>();
3610        for (EventGeneratingExp exp : exps) {
3611            if (exp.hasIndicator()) {
3612                res.addAll(exp.myIndicatorVariables());
3613            }
3614        }
3615        return res;
3616    }
3617
3618    /**
3619     * Returns all variables known to this equation that are part of the
3620     * equation system, e.g. variables in the attributes isn't included in this
3621     * list.
3622     * <p>
3623     * Word of causion, this method is used for debug output right now and I
3624     * got a feeling that it might return the same variable twice! So test well
3625     * if you're going to use it "for real".
3626     */
3627    syn Iterable<FVariable> FAbstractEquation.allVariables() {
3628        return new ChainedIterable<FVariable>(variables(), discretePreVariables(), parameters());
3629    }
3630
3631    /**
3632     * Get the differenetiated variabel (FVariable) corresponding to
3633     * a derivative variable (FDerivativeVariable)
3634     */
3635    syn FAbstractVariable FVariable.myDifferentiatedVariable() {
3636        if (order() <= 0) {
3637            return unknownFVariable();
3638        } else if (order() == 1) {
3639            return getFAccess().myFV();
3640        } else {
3641            return getFAccess().myDerFV(order() - 1);
3642        }
3643    }
3644
3645    /**
3646     * Get the derivative variabel (FDerivativeVariable) corresponding to
3647     * a differentiated variable (FVariable)
3648     */
3649    syn FAbstractVariable FVariable.myDerivativeVariable() = getFAccess().myDerFV(order() + 1);
3650
3651    /**
3652     * Get the pre variable connected to a normal variable, if any.
3653     */
3654    syn FAbstractVariable FAbstractVariable.myPreVariable() = getFAccess().myPreFV();
3655   
3656    /**
3657     * Get the normal variable connected to a pre variable.
3658     *
3659     * Will be unknown for non-pre variables.
3660     */
3661    syn FAbstractVariable FAbstractVariable.myNonPreVariable() = getFAccess().myFV();
3662}
3663
3664aspect LinearFVariables {
3665   
3666    /**
3667     * Check linearity of variable.
3668     *
3669     * The attribute isLinear returns true if all uses of the variable appears
3670     * linearly in equations and in initial equations. Parameters and constants
3671     * are assumed to be literals in the linearity computation. Accordingly,
3672     * multiplication of a variable with a parameter or constant does not render
3673     * the variable nonlinear. Also, parameters and constants are considered
3674     * to be linear themselves.
3675     */
3676    syn lazy boolean FVariable.isLinear() {
3677        if (isParameter() || isConstant()) {
3678            return true;
3679        }
3680        for (FAccessExp e : uses()) {
3681            if (!e.isLinear()) {
3682                return false;
3683            }
3684        }
3685        return true;
3686    }
3687   
3688    /**
3689     * Check if a subexpression appears linearly.
3690     *
3691     * Note that this method does not check if the expression itself is linear
3692     * but wheather it apperas linearly in a composite expression. For example
3693     * the sub expression 'sin(x)' appears linearly in '1+sin(x)'.
3694     */
3695    inh boolean FExp.isLinear();
3696    eq FlatRoot.getChild().isLinear() = true;
3697    eq SourceRoot.getChild().isLinear() = true;
3698   
3699    eq FAbstractEquation.getChild().isLinear() = true;
3700   
3701    eq FDotMulExp.getLeft().isLinear() =
3702        (getRight().isConstantExp() || getRight().isLinearParameterExp())?
3703                isLinear() : false;
3704    eq FDotMulExp.getRight().isLinear() =
3705        (getLeft().isConstantExp() || getLeft().isLinearParameterExp())?
3706                isLinear() : false;
3707    eq FDotDivExp.getLeft().isLinear() =
3708        (getRight().isConstantExp() || getRight().isLinearParameterExp())?
3709                isLinear() : false;
3710    eq FDotDivExp.getRight().isLinear() = false;
3711    eq FDotPowExp.getChild().isLinear() = false;
3712    eq FFunctionCall.getChild().isLinear() = false;
3713    eq FMathematicalFunctionCall.getChild().isLinear() = false;
3714               
3715    // This definition is to avoid errors when isParameterExp is redefined
3716    // to include free parameters in the Optimica extension.
3717    syn boolean FExp.isLinearParameterExp() = isParameterExp();
3718   
3719    syn boolean FAbstractEquation.checkLinearity(Set<FVariable> vars) {
3720        for (FAccessExp e : referencedCommonAccessExps()) {
3721            if (vars.contains(e.myFV()) && !e.isLinear(vars)) {
3722                return false;
3723            }
3724        }
3725        return true;
3726    }
3727    eq FIfWhenElseEquation.checkLinearity(Set<FVariable> vars) = false;
3728    eq FAlgorithm.checkLinearity(Set<FVariable> vars) = false;
3729   
3730    inh boolean FExp.isLinear(Set<FVariable> vars);
3731    eq FlatRoot.getChild().isLinear(Set<FVariable> vars)   = true;
3732    eq SourceRoot.getChild().isLinear(Set<FVariable> vars) = true;
3733   
3734    eq FAbstractEquation.getChild().isLinear(Set<FVariable> vars) = true;
3735    eq FStatement.getChild().isLinear(Set<FVariable> vars)        = false;
3736   
3737    eq FDotMulExp.getLeft().isLinear(Set<FVariable> vars)  = getRight().isIndependent(vars) && isLinear(vars);
3738    eq FDotMulExp.getRight().isLinear(Set<FVariable> vars) = getLeft().isIndependent(vars) && isLinear(vars);
3739    eq FDotDivExp.getLeft().isLinear(Set<FVariable> vars)  = getRight().isIndependent(vars) && isLinear(vars);
3740    eq FDotDivExp.getRight().isLinear(Set<FVariable> vars) = false;
3741    eq FDotPowExp.getChild().isLinear(Set<FVariable> vars) = false;
3742    eq FFunctionCall.getChild().isLinear(Set<FVariable> vars) = false;
3743    eq FMathematicalFunctionCall.getChild().isLinear(Set<FVariable> vars) = false;
3744    eq FAbstractFunctionCall.getChild().isLinear(Set<FVariable> vars) = false;
3745    eq FIfExp.getIfExp().isLinear(Set<FVariable> vars) = !isWhen() && (!inNoEventExp() || getIfExp().isIndependent(vars)); 
3746    eq FNoEventExp.getFExp().isLinear(Set<FVariable> vars) = isLinear(vars);
3747   
3748    syn boolean FExp.isIndependent(Set<? extends CommonVariableDecl> set) {
3749        for (FExp e : childFExps()) {
3750            if (!e.isIndependent(set)) {
3751                return false;
3752            }
3753        }
3754        return true;
3755    }
3756
3757    syn boolean FIfExp.isIndependent(Set<? extends CommonVariableDecl> set) {
3758        // Don't check the guard exp since it is discrete and does not affect
3759        // linearity.
3760        return getThenExp().isIndependent(set) && getElseExp().isIndependent(set);
3761    }
3762
3763    eq FAbstractDerExp.isIndependent(Set<? extends CommonVariableDecl> set) {
3764        return !set.contains(myFV());
3765    }
3766
3767    eq FAccessExp.isIndependent(Set<? extends CommonVariableDecl> set) {
3768        return getFAccess().isIndependent(set);
3769    }
3770
3771    syn boolean CommonAccess.isIndependent(Set<? extends CommonVariableDecl> set);
3772   
3773    eq FAccess.isIndependent(Set<? extends CommonVariableDecl> set) {
3774        return !set.contains(myFV());
3775    }
3776
3777    eq InstAccess.isIndependent(Set<? extends CommonVariableDecl> set) {
3778        return !set.contains(myInstComponentDecl());
3779    }
3780
3781}
3782
3783aspect FlatDiagnostics {
3784
3785    syn String FClass.diagnostics() {
3786        StringBuilder str = new StringBuilder();
3787        str.append("Diagnostics for flattened class " + name() + "\n");
3788
3789        str.append(modelDiagnostics());
3790       
3791        str.append("\n");
3792       
3793        str.append(variableDiagnostics());
3794       
3795        str.append("\n"); 
3796
3797        str.append(aliasDiagnostics());
3798       
3799        str.append("\n"); 
3800       
3801        str.append(incidence());
3802
3803        str.append("\n"); 
3804       
3805        str.append(dependencyDiagnostics());
3806
3807        str.append("\n");
3808       
3809//      str.append(dersAndDiffs());
3810       
3811        str.append("\n"); 
3812       
3813        str.append(connectionSetDiagnostics());
3814       
3815        return str.toString();
3816    }
3817
3818    public String FClass.modelDiagnostics() {
3819        StringBuilder str = new StringBuilder();
3820        modelDiagnosticsPrintRow(str, "Number of independent constants:", independentConstants());
3821        modelDiagnosticsPrintRow(str, "  Number of Real independent constants:", independentRealConstants());
3822        modelDiagnosticsPrintRow(str, "  Number of Real independent constants:", independentRealConstants());
3823        modelDiagnosticsPrintRow(str, "  Number of Integer independent constants:", independentIntegerConstants());
3824        modelDiagnosticsPrintRow(str, "  Number of Enum independent constants:", independentEnumConstants());
3825        modelDiagnosticsPrintRow(str, "  Number of Boolean independent constants:", independentBooleanConstants());
3826        modelDiagnosticsPrintRow(str, "  Number of String independent constants:", independentStringConstants());
3827
3828        modelDiagnosticsPrintRow(str, "Number of dependent constants:", dependentConstants());
3829        modelDiagnosticsPrintRow(str, "  Number of Real dependent constants:", dependentRealConstants());
3830        modelDiagnosticsPrintRow(str, "  Number of Integer dependent constants:", dependentIntegerConstants());
3831        modelDiagnosticsPrintRow(str, "  Number of Enum dependent constants:", dependentEnumConstants());
3832        modelDiagnosticsPrintRow(str, "  Number of Boolean dependent constants:", dependentBooleanConstants());
3833        modelDiagnosticsPrintRow(str, "  Number of String dependent constants:", dependentStringConstants());
3834
3835        modelDiagnosticsPrintRow(str, "Number of independent parameters:", independentParameters());
3836        modelDiagnosticsPrintRow(str, "  Number of Real independent parameters:", independentRealParameters());
3837        modelDiagnosticsPrintRow(str, "  Number of Integer independent parameters:", independentIntegerParameters());
3838        modelDiagnosticsPrintRow(str, "  Number of Enum independent parameters:", independentEnumParameters());
3839        modelDiagnosticsPrintRow(str, "  Number of Boolean independent parameters:", independentBooleanParameters());
3840        modelDiagnosticsPrintRow(str, "  Number of String independent parameters:", independentStringParameters());
3841                 
3842        modelDiagnosticsPrintRow(str, "Number of dependent parameters:", dependentParameters());
3843        modelDiagnosticsPrintRow(str, "  Number of Real dependent parameters:", dependentRealParameters());
3844        modelDiagnosticsPrintRow(str, "  Number of Integer dependent parameters:", dependentIntegerParameters());
3845        modelDiagnosticsPrintRow(str, "  Number of Enum dependent parameters:", dependentEnumParameters());
3846        modelDiagnosticsPrintRow(str, "  Number of Boolean dependent parameters:", dependentBooleanParameters());
3847        modelDiagnosticsPrintRow(str, "  Number of String dependent parameters:", dependentStringParameters());
3848       
3849        modelDiagnosticsPrintRow(str, "Number of initial parameters:", initialParameters());
3850        modelDiagnosticsPrintRow(str, "  Number of Real dependent parameters:", realInitialParameters());
3851        modelDiagnosticsPrintRow(str, "  Number of Integer dependent parameters:", integerInitialParameters());
3852        modelDiagnosticsPrintRow(str, "  Number of Enum dependent parameters:", enumInitialParameters());
3853        modelDiagnosticsPrintRow(str, "  Number of Boolean dependent parameters:", booleanInitialParameters());
3854        modelDiagnosticsPrintRow(str, "  Number of String dependent parameters:", stringInitialParameters());
3855       
3856        modelDiagnosticsPrintRow(str, "Number of variables:", variables());
3857        modelDiagnosticsPrintRow(str, "  Number of Real variables:", realVariables());
3858        modelDiagnosticsPrintRow(str, "  Number of Integer variables:", integerVariables());
3859        modelDiagnosticsPrintRow(str, "  Number of Enum variables:", enumVariables());
3860        modelDiagnosticsPrintRow(str, "  Number of Boolean variables:", booleanVariables());
3861        modelDiagnosticsPrintRow(str, "  Number of String variables:", stringVariables());
3862
3863        modelDiagnosticsPrintRow(str, "Number of Real differentiated variables:", differentiatedRealVariables()); 
3864        modelDiagnosticsPrintRow(str, "Number of Real derivative variables:", derivativeVariables()); 
3865        modelDiagnosticsPrintRow(str, "Number of Real continous algebraic variables:", algebraicContinousRealVariables());
3866
3867        modelDiagnosticsPrintRow(str, "Number of inputs:", inputs());
3868        modelDiagnosticsPrintRow(str, "  Number of Real inputs:", realInputs());
3869        modelDiagnosticsPrintRow(str, "  Number of Integer inputs:", integerInputs());
3870        modelDiagnosticsPrintRow(str, "  Number of Enum inputs:", enumInputs());
3871        modelDiagnosticsPrintRow(str, "  Number of Boolean inputs:", booleanInputs());
3872        modelDiagnosticsPrintRow(str, "  Number of String inputs:", stringInputs());
3873       
3874        modelDiagnosticsPrintRow(str, "Number of discrete variables:", discreteVariables());
3875        modelDiagnosticsPrintRow(str, "  Number of Real discrete variables:", discreteRealVariables());
3876        modelDiagnosticsPrintRow(str, "  Number of Integer discrete variables:", discreteIntegerVariables());
3877        modelDiagnosticsPrintRow(str, "  Number of Enum discrete variables:", discreteEnumVariables());
3878        modelDiagnosticsPrintRow(str, "  Number of Boolean discrete variables:", discreteBooleanVariables());
3879        modelDiagnosticsPrintRow(str, "  Number of String discrete variables:", discreteStringVariables());
3880       
3881        modelDiagnosticsPrintRow(str, "Number of equations:", equations());
3882       
3883        modelDiagnosticsPrintRow(str, "Number of variables with binding expression:", variablesWithBindingExp());
3884        modelDiagnosticsPrintRow(str, "  Number of Real variables with binding exp:", realVariablesWithBindingExp());
3885        modelDiagnosticsPrintRow(str, "  Number of Integer variables binding exp:", integerVariablesWithBindingExp());
3886        modelDiagnosticsPrintRow(str, "  Number of Enum variables binding exp:", enumVariablesWithBindingExp());
3887        modelDiagnosticsPrintRow(str, "  Number of Boolean variables binding exp:", booleanVariablesWithBindingExp());
3888        modelDiagnosticsPrintRow(str, "  Number of String variables binding exp:", stringVariablesWithBindingExp());
3889           
3890        modelDiagnosticsPrintRow(str, "Total number of equations:", equations(), variablesWithBindingExp());
3891   
3892        modelDiagnosticsPrintRow(str, "Number of initial equations:", initialEquations());
3893
3894        str.append(String.format("Number of event indicators in equations:      %6d\n", numEventIndicators()));
3895        str.append(String.format("Number of event indicators in init equations: %6d\n", numRelExpInInitialEquations()));
3896
3897
3898        return str.toString();
3899    }
3900   
3901    private static void FClass.modelDiagnosticsPrintRow(StringBuilder sb, String label, Collection<? extends FDiagnosticsNode> ... lists) {
3902        int num = 0;
3903        int numScalar = 0;
3904        for (Collection<? extends FDiagnosticsNode> list : lists) {
3905            num += list.size();
3906            numScalar += countNumScalars(list);
3907        }
3908        sb.append(String.format("%-46s%6d(%5d scalars)\n", label, num, numScalar));
3909    }
3910
3911    private static int FClass.countNumScalars(Collection<? extends FDiagnosticsNode> nodes) {
3912        int num = 0;
3913        for (FDiagnosticsNode node : nodes)
3914            num += node.numScalars();
3915        return num;
3916    }
3917
3918    public interface FDiagnosticsNode {
3919        public int numScalars();
3920    }
3921    public class FAbstractEquation implements FDiagnosticsNode {}
3922    public class FVariable implements FDiagnosticsNode {}
3923   
3924    syn int FAbstractEquation.numScalars() = numScalarEquations();
3925    syn int FVariable.numScalars() = type().numScalarElements();
3926   
3927    public String FClass.aliasDiagnostics() {
3928        StringBuilder str = new StringBuilder();
3929        str.append("Alias sets:\n");
3930        if (getAliasManager()!=null) {
3931            str.append(getAliasManager());
3932            int n_elim = 0;
3933            for (AliasManager.AliasSet aliasSet : getAliasManager().getAliasSets()) {
3934                n_elim += aliasSet.numAliases() - 1;
3935            }
3936            str.append(n_elim + " variables can be eliminated\n");
3937               
3938        } else {
3939            str.append("  Alias sets not computed.\n");
3940        }
3941        return str.toString(); 
3942       
3943    }
3944
3945    public String FClass.aliasDiagnosticsShort() {
3946        StringBuilder str = new StringBuilder();
3947        if (getAliasManager()!=null) {
3948            int n_elim = 0;
3949            Set<AliasManager.AliasSet> aliasSets = getAliasManager().getAliasSets();
3950            for (AliasManager.AliasSet aliasSet : aliasSets) {
3951                n_elim += aliasSet.numAliases() - 1;
3952            }
3953            str.append(aliasSets.size());
3954            str.append(" sets, ");
3955            str.append(n_elim);
3956            str.append(" eliminated variables");
3957        } else {
3958            str.append("Alias sets not computed");
3959        }
3960        return str.toString(); 
3961       
3962    }
3963
3964    public String FClass.variableDiagnostics() {
3965       
3966        StringBuilder str = new StringBuilder();
3967       
3968        str.append("Independent constants: \n");
3969        for (FVariable fv : independentConstants()) {
3970            str.append(" " + fv.name());
3971            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
3972                    + fv.isLinear());
3973                str.append("\n");
3974        }
3975        str.append("\n");
3976       
3977        str.append("Dependent constants: \n");
3978        for (FVariable fv : dependentConstants()) {
3979            str.append(" " + fv.name());
3980            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
3981                    + fv.isLinear());
3982                str.append("\n");
3983        }
3984        str.append("\n");
3985       
3986        str.append("Independent parameters: \n");
3987        for (FVariable fv : independentParameters()) {
3988            str.append(" " + fv.name());
3989            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
3990                    + fv.isLinear());
3991            if (fv.hasBindingExp()) {
3992                CValue val = CValue.UNKNOWN;
3993                try {
3994                    val = fv.getBindingExp().ceval();
3995                } catch (ConstantEvaluationException e) {
3996                   
3997                }
3998                str.append(", evaluated binding exp: ");
3999                str.append(val);
4000            }
4001            str.append("\n");
4002        }
4003        str.append("\n");
4004       
4005        str.append("Dependent parameters: \n");
4006        for (FVariable fv : dependentParameters()) {
4007            str.append(" " + fv.name());
4008            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
4009                    + fv.isLinear());
4010                str.append("\n");
4011        }
4012
4013        str.append("\n"); 
4014        str.append("Differentiated variables: \n");
4015        for (FVariable fv : differentiatedRealVariables()) {
4016            str.append(" " + fv.name());
4017            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
4018                    + fv.isLinear());
4019            str.append("\n");
4020        }
4021
4022        str.append("\n"); 
4023        str.append("Derivative variables: \n");
4024        for (FVariable fv : derivativeVariables()) {
4025            str.append(" " + fv.name());
4026            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
4027                    + fv.isLinear());
4028                str.append("\n");
4029        }
4030        str.append("\n"); 
4031
4032        str.append("Discrete variables: \n");
4033        for (FVariable fv : discreteVariables()) {
4034            str.append(" " + fv.name());
4035            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
4036                    + fv.isLinear());
4037            str.append(", alias: ");
4038            if (!fv.isAlias()) {
4039                str.append("no");
4040            } else {
4041                if (fv.isNegated()) {
4042                    str.append("-");
4043                }
4044                str.append(fv.alias().valueReference());
4045            }
4046            str.append("\n");
4047        }
4048        str.append("\n");
4049       
4050        str.append("Algebraic real variables: \n");
4051        for (FVariable fv : algebraicContinousRealVariables()) {
4052            str.append(" " + fv.name());
4053            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
4054                    + fv.isLinear());
4055            str.append(", alias: ");
4056            if (!fv.isAlias()) {
4057                str.append("no");
4058            } else {
4059                if (fv.isNegated()) {
4060                    str.append("-");
4061                }
4062                str.append(fv.alias().valueReference());
4063            }
4064            str.append("\n");
4065        }
4066        str.append("\n");
4067       
4068        str.append("Input variables: \n");
4069        for (FVariable fv : inputs()) {
4070            str.append(" " + fv.name());
4071            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
4072                    + fv.isLinear());
4073                str.append("\n");
4074        }
4075
4076        return str.toString();
4077       
4078    }
4079
4080    public String FClass.dependencyDiagnostics() {
4081       
4082        StringBuilder str = new StringBuilder();
4083           
4084        if (myOptions().getBooleanOption("equation_sorting")) {
4085           
4086            str.append("Variable dependencies:\n");
4087           
4088            if (getNumFVariable() > myOptions().getIntegerOption("diagnostics_limit")) {
4089                str.append("Oh dear, the model has way to many variables (" + getNumFVariable() + ")!\n");
4090                str.append("Current limit is set to " + myOptions().getIntegerOption("diagnostics_limit") + ", you can change this by changing the option 'diagnostics_limit'.\n");
4091                return str.toString();
4092            }
4093           
4094            str.append("Derivative variables: \n");
4095            for (FVariable fv : derivativeVariables()) {
4096                str.append(" " + fv.name() + "\n");
4097                for (FVariable d : fv.dependsOn()) {
4098                    str.append("    " + d.name() + "\n");
4099                }
4100            }
4101            str.append("\n");
4102            str.append("Differentiated variables: \n");
4103            for (FVariable fv : differentiatedRealVariables()) {
4104                str.append(" " + fv.name() + "\n");
4105                for (FVariable d : fv.dependsOn()) {
4106                    str.append("    " + d.name() + "\n");
4107                }
4108            }
4109            str.append("\n");
4110            str.append("Algebraic real variables: \n");
4111            for (FVariable fv : algebraicContinousRealVariables()) {
4112                str.append(" " + fv.name() + "\n");
4113                for (FVariable d : fv.dependsOn()) {
4114                    str.append("    " + d.name() + "\n");
4115                }
4116            }
4117            str.append("\n");
4118        }
4119        return str.toString();
4120    }
4121   
4122    public String FClass.directDependencyDiagnostics() {
4123        StringBuilder sb = new StringBuilder();
4124        for (FVariable output : realOutputs()) {
4125            sb.append(output.name());
4126            sb.append("\n");
4127            for (FVariable input : output.directDependencies()) {
4128                sb.append("    ");
4129                sb.append(input.name());
4130                sb.append("\n");
4131            }
4132        }
4133        return sb.toString();
4134    }   
4135   
4136    public Set<FVariable> FVariable.directDependencies() {
4137        Set<FVariable> res = new LinkedHashSet<FVariable>();
4138        for (FVariable dv : dependsOn()) {
4139            if (dv.isInput()) {
4140                res.add(dv);
4141            }
4142        }
4143        return res;
4144    }
4145
4146    public String FClass.connectionSetDiagnostics() {
4147        return getConnectionSetManager().printConnectionSets();
4148    }
4149   
4150    public String FClass.incidence() {
4151        return incidence(false);
4152    }
4153
4154    public String FClass.incidence(boolean printAllVariables) {
4155        StringBuilder str = new StringBuilder();
4156       
4157        str.append("Incidence:\n");
4158       
4159        int i = 0;
4160        for (FAbstractEquation fe : equations()) {
4161            Iterable<? extends FVariable> vars;
4162            if (printAllVariables) {
4163                vars = fe.allVariables();
4164            } else {
4165                vars = new ChainedIterable<FVariable>(fe.derivativeVariables(), fe.algebraicVariables());
4166            }
4167            str.append(" eq " + i + ":");
4168            for (FVariable var : vars) {
4169                str.append(" " + var.name());
4170            }
4171            str.append("\n");
4172            i++;
4173        }
4174       
4175        return str.toString();
4176    }
4177   
4178    public String FClass.dersAndDiffs() {
4179        StringBuilder str = new StringBuilder();
4180        str.append("Derivatives and differentiated variables:\n");
4181        for (FDerivativeVariable fdv : derivativeVariables()) {
4182            if (fdv.myDifferentiatedVariable()!=null) {
4183                str.append(" " + fdv.name() + ", " + fdv.myDifferentiatedVariable().name() + "\n");
4184            }
4185        }   
4186        str.append("Differentiated variables and derivatives:\n");
4187        for (FVariable fv : differentiatedRealVariables()) {
4188            if (fv.myDerivativeVariable()!=null) {
4189                str.append(" " + fv.name() + ", " + fv.myDerivativeVariable().name() + "\n");
4190            }
4191        }
4192        return str.toString();
4193       
4194    }
4195   
4196    public String FClass.printDAEBLT() {
4197        return getDAEBLT() == null ? "" : getDAEBLT().toString();
4198    }
4199
4200    public String FClass.printDAEInitBLT() {
4201        return getDAEInitBLT().toString();
4202    }
4203   
4204    public String FClass.printMatchedDAE() {
4205        return computeMatchedDAEBiPGraph(createBLTInput()).toString();
4206    }
4207
4208
4209    syn String FClass.attributeLevels() {
4210        StringBuilder str = new StringBuilder();
4211        str.append("Variables:\n");
4212        for (FVariable v : getFVariables())
4213            v.attributeLevels(str);
4214        for (FVariable v : getAliasVariables())
4215            v.attributeLevels(str);
4216        if (getNumFDerivedType() > 0) {
4217            str.append("\nTypes:\n");
4218            for (FDerivedType t : getFDerivedTypes())
4219                t.attributeLevels(str);
4220        }
4221        return str.toString();
4222    }
4223
4224    public void FVariable.attributeLevels(StringBuilder str) {
4225        str.append("  ");
4226        str.append(name());
4227        attributeLevelsForList(getFAttributes(), str);
4228        str.append("\n");
4229    }
4230
4231    public void FDerivedType.attributeLevels(StringBuilder str) {
4232        str.append("  ");
4233        str.append(getName());
4234        attributeLevelsForList(getFAttributes(), str);
4235        str.append("\n");
4236    }
4237
4238    public void FAttribute.attributeLevels(StringBuilder str) {
4239        str.append(name());
4240        str.append(":");
4241        str.append(getLevel());
4242        attributeLevelsForList(getFAttributes(), str);
4243        if (hasValue()) {
4244            str.append("=");
4245            str.append(getValue());
4246        }
4247    }
4248
4249    public static void ASTNode.attributeLevelsForList(List<FAttribute> l, StringBuilder str) {
4250        if (l.getNumChild() > 0) {
4251            str.append("(");
4252            String sep = ", ";
4253            String pref = "";
4254            for (FAttribute a : l) {
4255                str.append(pref);
4256                a.attributeLevels(str);
4257                pref = sep;
4258            }
4259            str.append(")");
4260        }
4261    }
4262
4263}
4264
4265aspect FlatAlgorithmAPI {
4266   
4267    syn boolean FExp.inFAlgorithm() = myFAlgorithm() != null;
4268   
4269    syn FAlgorithm FAccessExp.myFAlgorithm() = getFAccess().myFAlgorithm();
4270    inh lazy FAlgorithm CommonAccess.myFAlgorithm();
4271    inh lazy FAlgorithm FStatement.myFAlgorithm();
4272    inh FAlgorithm FExp.myFAlgorithm();
4273    eq FAbstractEquation.getChild().myFAlgorithm() = null;
4274    eq FAlgorithm.getChild().myFAlgorithm() = this;
4275    eq Root.getChild().myFAlgorithm() = null;
4276   
4277    coll ArrayList<FAlgorithm> FClass.myAlgorithms()
4278        [new ArrayList<FAlgorithm>()] with add root FClass;
4279    FAlgorithm contributes this when !inFunction()
4280        to FClass.myAlgorithms() for myFClass();
4281   
4282    inh boolean CommonAccess.useIsAssignment();
4283    inh boolean FAssignableExp.useIsAssignment();
4284    inh boolean FArray.useIsAssignment();
4285    inh boolean FRecordConstructor.useIsAssignment();
4286    eq FAssignStmt.getLeft().useIsAssignment()       = true;
4287    eq FFunctionCallLeft.getFExp().useIsAssignment() = true;
4288    eq FAssignableExp.getChild().useIsAssignment()   = useIsAssignment();
4289    eq FArraySubscripts.getChild().useIsAssignment() = false;
4290    eq FArray.getFExp().useIsAssignment()            = useIsAssignment();
4291    eq FRecordConstructor.getArg().useIsAssignment() = useIsAssignment();
4292    eq FExp.getChild().useIsAssignment()             = false;
4293    eq FStatement.getChild().useIsAssignment()       = false;
4294    eq FAlgorithm.getChild().useIsAssignment()       = false;
4295    eq Root.getChild().useIsAssignment()             = false;
4296   
4297    private String FAlgorithm.functionName = null;
4298    public String FAlgorithm.generateFunctionName() {
4299        if (functionName == null)
4300            functionName = myFClass().generateFunctionName();
4301        return functionName;
4302    }
4303    private int FClass.generatedFunctionNumber = 1;
4304    public String FClass.generateFunctionName() {
4305        String name, part;
4306        do {
4307            part = "algorithm_" + generatedFunctionNumber;
4308            name = name() + "." + part;
4309            generatedFunctionNumber++;
4310        } while (lookupFunc(name) != null || variablesMap().lookup(part) != null);
4311        return name;
4312    }
4313   
4314}
4315
4316aspect FlatExternalFunctionAPI {
4317   
4318    /**
4319     * Gives the arguments to pass to gcc required by external functions.
4320     */
4321    syn String FClass.externalCompilerArgs() {
4322        StringBuilder buf = new StringBuilder();
4323        for (String lib : externalLibraries()) {
4324            buf.append(" -l");
4325            buf.append(lib);
4326        }
4327        for (String dir : externalLibraryDirectories()) {
4328            buf.append(" -L");
4329            buf.append(dir);
4330        }
4331        for (String dir : externalIncludeDirectories()) {
4332            buf.append(" -I");
4333            buf.append(dir);
4334        }
4335        return buf.toString();
4336    }
4337
4338    syn String FClass.externalLibArgs() {
4339        StringBuilder buf = new StringBuilder();
4340        for (String lib : externalLibraries()) {
4341            buf.append(" -l");
4342            buf.append(lib);
4343        }
4344        for (String dir : externalLibraryDirectories()) {
4345            buf.append(" -L");
4346            buf.append(dir);
4347        }
4348        return buf.toString();
4349    }
4350
4351    syn String FClass.externalIncludeArgs() {
4352        StringBuilder buf = new StringBuilder();
4353        for (String dir : externalIncludeDirectories()) {
4354            buf.append(" -I");
4355            buf.append(dir);
4356        }
4357        return buf.toString();
4358    }
4359   
4360    coll HashSet<FExternalStmt> FClass.myExternals()
4361        [new LinkedHashSet<FExternalStmt>()] with add root FClass;
4362    FExternalStmt contributes this
4363        to FClass.myExternals() for myFClass();
4364   
4365    syn HashSet<String> FClass.externalLibraries() {
4366        HashSet<String> res = new LinkedHashSet<String>();
4367        for (FExternalStmt ext : myExternals())
4368            if (ext.library() != null)
4369                for (String lib : ext.library())
4370                    res.add(lib);
4371        return res;
4372    }
4373   
4374    syn HashSet<String> FClass.externalIncludes() {
4375        HashSet<String> res = new LinkedHashSet<String>();
4376        for (FExternalStmt ext : myExternals())
4377            if (ext.include() != null)
4378                res.add(ext.include());
4379        return res;
4380    }
4381   
4382    syn HashSet<String> FClass.externalLibraryDirectories() {
4383        HashSet<String> res = new LinkedHashSet<String>();
4384        for (FExternalStmt ext : myExternals())
4385            if (ext.libraryDirectory() != null)
4386                res.add(ext.libraryDirectory());
4387        return res;
4388    }
4389   
4390    syn HashSet<String> FClass.externalIncludeDirectories() {
4391        HashSet<String> res = new LinkedHashSet<String>();
4392        for (FExternalStmt ext : myExternals())
4393            if (ext.includeDirectory() != null)
4394                res.add(ext.includeDirectory());
4395        return res;
4396    }
4397   
4398    syn String[] FExternalStmt.library() = library;
4399    syn String FExternalStmt.include()            = include;
4400    syn String FExternalStmt.libraryDirectory()   = libraryDir;
4401    syn String FExternalStmt.includeDirectory()   = includeDir;
4402    syn boolean FExternalStmt.isIncluded() = !(include() == null || include().equals(""));
4403    syn boolean FExternalStmt.isInLibrary() = !(libraryDirectory() == null || libraryDirectory().equals(""));
4404   
4405    private String[] FExternalStmt.library;
4406    private String FExternalStmt.include;
4407    private String FExternalStmt.libraryDir;
4408    private String FExternalStmt.includeDir;
4409   
4410    public void FExternalStmt.extractLibrary(FExternalStmt n) {
4411        this.library = n.library;
4412        this.include = n.include;
4413        this.libraryDir = n.libraryDir;
4414        this.includeDir = n.includeDir;
4415    }
4416   
4417    public void FExternalStmt.extractLibrary(InstExternal n) {
4418        library = n.annotation("Library").asStringVector();
4419        include = n.annotation("Include").string();
4420        libraryDir = n.annotation("LibraryDirectory").string();
4421        includeDir = n.annotation("IncludeDirectory").string();
4422       
4423        if (libraryDir == null || includeDir == null) {
4424            String libraryName = n.libraryName();
4425            if (libraryName != null) {
4426                String defDir = "modelica://" + libraryName + "/Resources";
4427                libraryDir = (libraryDir == null && library != null) ? 
4428                        defDir + "/Library" : libraryDir;
4429                includeDir = (includeDir == null && include != null) ? 
4430                        defDir + "/Include" : includeDir;
4431            }
4432        }
4433       
4434        if (includeDir != null) 
4435            includeDir = URIResolver.DEFAULT.resolve(n, includeDir);
4436        if (libraryDir != null) {
4437            libraryDir = URIResolver.DEFAULT.resolve(n, libraryDir);
4438        }
4439    }
4440
4441}
4442
4443aspect ExpressionGeneralisation {
4444    /**
4445     * Returns the expression stripped of any negations
4446     */
4447    syn FExp FExp.stripNegations()     = this;
4448    eq FNegExp.stripNegations()        = getFExp().stripNegations();
4449   
4450   
4451    syn boolean FEquation.isNegated() = getLeft().isNegated() ^ getRight().isNegated();
4452   
4453    /**
4454     * Check if the expressions is negated
4455     */
4456    syn boolean FExp.isNegated()  = false;
4457    eq FNegExp.isNegated()        = !getFExp().isNegated();
4458   
4459    /**
4460     * Return this expression negated if <code>neg</code> is true.
4461     */
4462    syn FExp FExp.negated(boolean neg) {
4463        if (neg)
4464            return new FNegExp(unboundCopy());
4465        else
4466            return unboundCopy();
4467    }
4468
4469    /**
4470     * The format string including the implicit leading "%", if the format argument is given.
4471     */
4472    syn lazy Opt<FExp> FStringExp.getCFormatOpt() {
4473        // TODO: To save memory, this could be solved in the C code generation instead.
4474        if (hasFormat()) {
4475            boolean hasPercent = formatSpecifier().initialPercent;
4476            FExp fmt = getFormat();
4477            FExp exp = fmt.treeCopy();
4478            if (!formatSpecifier().initialPercent) {
4479                exp = new FStringAddExp(new FStringLitExp("%"), exp);
4480            }
4481            if (fmt.variability().fixedParameterOrLess()) {
4482                try {
4483                    exp.parent = this;
4484                    exp = exp.ceval().buildLiteral();
4485                } catch (ConstantEvaluationException e) {
4486                    // If we can't evaluate, just leave it as is
4487                }
4488            }
4489            return new Opt<FExp>(exp);
4490        } else {
4491            return new Opt<FExp>();
4492        }
4493    }
4494}
Note: See TracBrowser for help on using the repository browser.