source: trunk/Compiler/ModelicaFlatTree/src/jastadd/FlatAPI/FlatAPI.jrag @ 13944

Last change on this file since 13944 was 13944, checked in by Jesper Mattsson, 5 weeks ago

Added a try-catch for a missed possible ConstantEvaluationException. (#5835)

File size: 199.3 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 FDerivedType.myFClass();
2371    inh FClass FEnumDecl.myFClass();
2372    inh FClass FAlgorithm.myFClass();
2373    inh FClass FAbstractEquation.myFClass();
2374    inh FClass FStatement.myFClass();
2375    inh FClass FFunctionCallLeft.myFClass();
2376    inh lazy FClass FExternalStmt.myFClass();
2377    eq FClass.getChild().myFClass() = this;
2378    eq Root.getChild().myFClass() = null; 
2379   
2380    public Iterable<FAbstractEquation> FExp.enclosingEquationsIterator() {
2381        return myFEquation().enclosingEquationsIterator();
2382    }
2383
2384    public Iterable<FAbstractEquation> FStatement.enclosingEquationsIterator() {
2385        return myFEquation().enclosingEquationsIterator();
2386    }
2387   
2388    inh FAbstractEquation FAbstractEquation.enclosingEquation();
2389    eq FAbstractEquation.getChild().enclosingEquation() = this;
2390    eq Root.getChild().enclosingEquation()              = null;
2391   
2392    /**
2393     * Returns the outermost enclosing equation or the equation itself if it is
2394     * the outermost.
2395     */
2396    syn FAbstractEquation FAbstractEquation.outermostEnclosingEquation() {
2397        FAbstractEquation enclosing = this;
2398        FAbstractEquation next = enclosingEquation();
2399        while (next != null) {
2400            enclosing = next;
2401            next = enclosing.enclosingEquation();
2402        }
2403        return enclosing;
2404    }
2405   
2406    /**
2407     * Returns an iterable that can be used to iterate over all surounding
2408     * equations (including this one).
2409     */
2410    public Iterable<FAbstractEquation> FAbstractEquation.enclosingEquationsIterator() {
2411        return new Iterable<FAbstractEquation>() {
2412
2413            @Override
2414            public Iterator<FAbstractEquation> iterator() {
2415                return new Iterator<FAbstractEquation>() {
2416
2417                    private FAbstractEquation next = FAbstractEquation.this;
2418                   
2419                    @Override
2420                    public boolean hasNext() {
2421                        return next != null;
2422                    }
2423
2424                    @Override
2425                    public FAbstractEquation next() {
2426                        FAbstractEquation res = next;
2427                        next = next.enclosingEquation();
2428                        return res;
2429                    }
2430
2431                    @Override
2432                    public void remove() {
2433                        throw new UnsupportedOperationException();
2434                    }
2435                   
2436                };
2437            }
2438           
2439        };
2440    }
2441   
2442    syn lazy boolean FVariable.isIndependentConstant() = isConstant();
2443    syn lazy boolean FVariable.isDependentConstant() = false;
2444   
2445    syn boolean FAbstractVariable.isDependentParameter() = false;
2446    syn lazy boolean FVariable.isDependentParameter() = 
2447        isParameter() && !isIndependentParameter();
2448   
2449    syn boolean FAbstractVariable.isIndependentParameter() = false;
2450    syn lazy boolean FVariable.isIndependentParameter() =
2451            isParameter() && !isInitialParameter() && !hasParameterEquation() && 
2452            (!hasBindingExp() || getBindingExp().isIndependentParameterExp());
2453   
2454    syn lazy boolean FVariable.isRegularIndependentParameter() =
2455        isIndependentParameter() && !variability().knownParameterOrLess();
2456    syn lazy boolean FVariable.isStructuralIndependentParameter() =
2457        isIndependentParameter() && variability().knownParameterOrLess();
2458    syn lazy boolean FVariable.isFinalIndependentParameter() =
2459        false; // TODO
2460    syn lazy boolean FVariable.isEvalIndependentParameter() =
2461        false; // TODO
2462
2463    syn boolean FExp.isIndependentParameterExp() = isConstantExp() && !hasCompositeFunc();
2464   
2465    inh boolean FAbstractEquation.isParameterEquation();
2466    eq FClass.getParameterEquation().isParameterEquation() = true;
2467    eq Root.getChild().isParameterEquation() = false;
2468   
2469    inh boolean FAbstractEquation.isNormalEquation();
2470    eq FClass.getFAbstractEquation().isNormalEquation() = true;
2471    eq FClass.getChild().isNormalEquation()             = false;
2472    eq InstNode.getChild().isNormalEquation()           = true;
2473    eq Root.getChild().isNormalEquation()               = false;
2474   
2475    inh List<FAbstractEquation> FAbstractEquation.myFAbstractEquationList();
2476    eq FClass.getFAbstractEquation().myFAbstractEquationList() = getFAbstractEquations();
2477    eq FClass.getFInitialEquation().myFAbstractEquationList() = getFInitialEquations();
2478    eq FClass.getParameterEquation().myFAbstractEquationList() = getParameterEquations();
2479    eq FClass.getChild().myFAbstractEquationList() = null;
2480    eq Root.getChild().myFAbstractEquationList() = null;
2481   
2482    coll ArrayList<FExp> FAbstractEquation.replacedAtInitialExps()
2483        [new ArrayList<FExp>()] with add root FAbstractEquation;
2484    FDelayExp contributes this
2485        to FAbstractEquation.replacedAtInitialExps() for myFEquation();
2486    FSpatialDistExp contributes this
2487        to FAbstractEquation.replacedAtInitialExps() for myFEquation();
2488   
2489    syn boolean FAbstractEquation.replacedAtInitialization() = 
2490            isWhen() || replacedAtInitialExps().size() > 0;
2491    eq FAlgorithm.replacedAtInitialization() {
2492        if (super.replacedAtInitialization())
2493            return true;
2494       
2495        /*
2496         * Even if there are no when statements, there might still be discrete
2497         * variables which are dependent on their pre() variables
2498         */
2499        Set<FVariable> notDefSet = referencedFVariablesInLHS();
2500        notDefSet.removeAll(defSet());
2501        for (FVariable fv : notDefSet)
2502            if (fv.isDiscrete())
2503                return true;
2504        return false;
2505    }
2506   
2507    syn List<FAbstractEquation> FAbstractEquation.getInitialEquationList() {
2508        List<FAbstractEquation> l = new List<FAbstractEquation>();
2509        if (replacedAtInitialization()) {
2510            l.add((FAbstractEquation) copySymbolic());
2511        }
2512        return l;
2513    }
2514   
2515    eq FIfEquation.getInitialEquationList() {
2516        return createInitialEquationList();
2517    }
2518   
2519    syn List<FAbstractEquation> FIfWhenElseEquation.createInitialEquationList() {
2520        List<FAbstractEquation> l = new List<FAbstractEquation>();
2521        for (FAbstractEquation e : getFAbstractEquations()) {
2522            if (e.replacedAtInitialization()) {
2523                l.addAll(e.getInitialEquations());
2524            } else {
2525                l.add(e.copySymbolic());
2526            }
2527        }
2528        return l;
2529    }
2530   
2531    eq FIfWhenEquation.createInitialEquationList() {
2532        if (getTest().isInitialGuard())
2533            return super.createInitialEquationList();
2534        else if (hasElse())
2535            return getElse().createInitialEquationList();
2536        else
2537            return new List<FAbstractEquation>();
2538    }
2539   
2540
2541    rewrite FIfExp {
2542        when (isWhen() && isInitial()) to FExp {
2543            if (getIfExp().isInitialGuard())
2544                return getThenExp();
2545            else
2546                return getElseExp();
2547        }
2548    }
2549   
2550    rewrite FDelayExp {
2551        when (isInitial()) to FExp {
2552            return getFExp().copySymbolic();
2553        }
2554    }
2555   
2556    rewrite FSpatialDistExp {
2557        when (isInitial() && !isFunctionCallClause()) to FExp {
2558            return createInitialReplacement(false);
2559        }
2560    }
2561   
2562    public FExp FSpatialDistExp.createInitialReplacement(boolean second) {
2563        int size = getInitialValues().size().numElements();
2564        return new FIfExp(getPositiveVelocity().copySymbolic(),
2565                getInitialValues().getArray().get(second ? size : 1).copySymbolic(), 
2566                getInitialValues().getArray().get(second ? 1 : size).copySymbolic());
2567    }
2568   
2569    eq FFunctionCallEquation.getInitialEquationList() {
2570        if (getCall() instanceof FSpatialDistExp) {
2571            FSpatialDistExp call = (FSpatialDistExp) getCall();
2572            ArrayList<FAbstractEquation> l = new ArrayList<FAbstractEquation>();
2573            if (getNumLeft() > 0 && getLeft(0).hasFExp()) {
2574                l.add(new FEquation(getLeft(0).getFExp().copySymbolic(), call.createInitialReplacement(false)));
2575            }
2576            if (getNumLeft() > 1 && getLeft(1).hasFExp()) {
2577                l.add(new FEquation(getLeft(1).getFExp().copySymbolic(), call.createInitialReplacement(true)));
2578            }
2579            return new List<FAbstractEquation>(l);
2580        }
2581        return super.getInitialEquationList();
2582    }
2583   
2584    eq FAlgorithm.getInitialEquationList() {
2585        ArrayList<FAbstractEquation> l = new ArrayList<FAbstractEquation>();
2586       
2587        // Keeps FAccessExps in lhs which have not been removed
2588        Set<FAccessExp> usesLHS = FAccessExpsInLHS();
2589       
2590        // Keeps track of which variables are definetly set
2591        Set<FVariable> fvSet  = new HashSet<FVariable>();
2592        Set<FVariable> fvUse  = new HashSet<FVariable>();
2593       
2594        // Create a new algorithm with some statements removed
2595        ArrayList<FStatement> stmts = new ArrayList<FStatement>();
2596        for (FStatement stmt : getFStatements()) {
2597            stmt.addAsInitial(stmts, usesLHS, fvSet, fvUse);
2598        }
2599       
2600        Set<FVariable> lhs = lookupFVariablesInSet(usesLHS);
2601
2602        // Add initial statements for variables which are not definetly set
2603        // in the new algorithm
2604        ArrayList<FStatement> initStmts = new ArrayList<FStatement>();
2605        for (FVariable fv : lhs)
2606            if (!fvSet.contains(fv))
2607                initStmts.add(new FAssignStmt(fv.createAccessExp(), fv.createAlgorithmArgument(true)));
2608        for (FStatement stmt : stmts)
2609            initStmts.add(stmt);
2610        if (initStmts.size() > 0)
2611            l.add(new FAlgorithm(new List<FStatement>(initStmts)));
2612       
2613        // Create equations for variables which are no longer assigned
2614        // in the new algorithm
2615        Set<FVariable> removedFVs = referencedFVariablesInLHS();
2616        removedFVs.removeAll(lhs);
2617        for (FVariable fv : removedFVs)
2618            l.add(new FEquation(fv.createAccessExp(), fv.createFPreExp()));
2619       
2620        return new List<FAbstractEquation>(l);
2621    }
2622   
2623   
2624    public void FStatement.addAsInitial(ArrayList<FStatement> stmts, Set<FAccessExp> usesLHS, 
2625            Set<FVariable> fvSet, Set<FVariable> fvUse) {
2626       
2627        defSet(fvSet, fvUse);
2628        stmts.add(copySymbolic());
2629    }
2630    public void FIfStmt.addAsInitial(ArrayList<FStatement> stmts, Set<FAccessExp> usesLHS, 
2631            Set<FVariable> fvSet, Set<FVariable> fvUse) {
2632       
2633        if (!isWhen()) {
2634            super.addAsInitial(stmts, usesLHS, fvSet, fvUse);
2635            return;
2636        }
2637       
2638        boolean first = true;
2639        for (FIfWhenClause c : getFIfWhenClauses()) {
2640            if (c.getTest().isInitialGuard() && first) {
2641                for (FStatement s : c.getFStatements()) {
2642                    s.defSet(fvSet, fvUse);
2643                    stmts.add(s.copySymbolic());
2644                }
2645                first = false;
2646            } else {
2647                usesLHS.removeAll(c.findFAccessExpsInTree());
2648            }
2649        }
2650    }
2651   
2652    syn boolean FExp.isInitialGuard() = false;
2653    eq FInitialExp.isInitialGuard() = true;
2654    eq FOrExp.isInitialGuard() = getLeft().isInitialGuard() || getRight().isInitialGuard();
2655           
2656    /**
2657     * Find LHS variables which are definetly assigned to before any use.
2658     */
2659    public Set<FVariable> FAlgorithm.defSet() {
2660        HashSet<FVariable> fvSet = new HashSet<FVariable>();
2661        HashSet<FVariable> fvUse = new HashSet<FVariable>();
2662        for (FStatement stmt : getFStatements()) {
2663            stmt.defSet(fvSet, fvUse);
2664        }
2665        return fvSet;
2666    }
2667    public void FStatement.defSetAdd(Set<FVariable> s1, Set<FVariable> s2, Collection<FVariable> fvs) {
2668        for (FVariable fv : fvs)
2669            if (!s1.contains(fv))
2670                s2.add(fv);
2671    }
2672    public void FStatement.defSet(Set<FVariable> fvSet, Set<FVariable> fvUse) {
2673        defSetAdd(fvSet, fvUse, lookupFVariablesInSet(FAccessExpsInRHS()));
2674    }
2675    public void FAssignStmt.defSet(Set<FVariable> fvSet, Set<FVariable> fvUse) {
2676        defSetAdd(fvSet, fvUse, lookupFVariablesInSet(getRight().findFAccessExpsInTree()));
2677        defSetAdd(fvUse, fvSet, lookupFVariablesInSet(getLeft().findFAccessExpsInTree()));
2678    }
2679    public void FFunctionCallStmt.defSet(Set<FVariable> fvSet, Set<FVariable> fvUse) {
2680        defSetAdd(fvSet, fvUse, lookupFVariablesInSet(getCall().findFAccessExpsInTree()));
2681        for (FFunctionCallLeft left : getLefts())
2682            if (left.hasFExp())
2683                defSetAdd(fvUse, fvSet, lookupFVariablesInSet(left.getFExp().findFAccessExpsInTree()));
2684    }
2685   
2686    /**
2687     * Check if tree contains a function call returning an array or a record.
2688     */
2689    syn boolean ASTNode.hasCompositeFunc() {
2690        for (ASTNode n : this)
2691            if (n.hasCompositeFunc())
2692                return true;
2693        return false;
2694    }
2695    eq InstFunctionCall.hasCompositeFunc() = 
2696        type().isArray() || type().isRecord() || super.hasCompositeFunc();
2697    eq FFunctionCall.hasCompositeFunc()    = 
2698        type().isArray() || type().isRecord() || super.hasCompositeFunc();
2699   
2700    syn boolean FVariable.hasParamValueExp() = hasBindingExp() || startAttributeSet();
2701    syn FExp FVariable.paramValueExp() = hasBindingExp() ? getBindingExp() : startAttributeExp();
2702   
2703    syn boolean FVariable.isVariable() = !isParameter() && !isConstant();
2704   
2705    syn boolean FAbstractVariable.isFVariable() = false;
2706    eq FVariable.isFVariable()                  = true;
2707
2708    syn boolean FAbstractVariable.isFRealVariable() = false;
2709    eq FRealVariable.isFRealVariable()              = true;
2710   
2711    syn boolean FAbstractVariable.isFFunctionVariable() = false;
2712    eq FFunctionVariable.isFFunctionVariable()          = true;
2713
2714    syn boolean FAbstractVariable.isDifferentiatedVariable() = false;
2715    syn lazy boolean FVariable.isDifferentiatedVariable() = zVariability() == FClass.ZVariability.DIFFERENTIATED;
2716    syn boolean FDynamicStateVariable.isDifferentiatedVariable() = true;
2717
2718    syn boolean FAbstractVariable.isAbstractDerivativeVariable() = false;
2719    eq FAbstractDerivativeVariable.isAbstractDerivativeVariable() = true;
2720
2721    syn boolean FAbstractVariable.isDerivativeVariable() = false;
2722    eq FDerivativeVariable.isDerivativeVariable() = true;
2723
2724    syn FVariable FAbstractVariable.asFVariable() {
2725        throw new UnsupportedOperationException("asFVariable() is not supported for class type " + getClass().getSimpleName());
2726    }
2727    eq FVariable.asFVariable() = this;
2728
2729    syn FRealVariable FAbstractVariable.asFRealVariable() {
2730        throw new UnsupportedOperationException("asFRealVariable() is not supported for class type " + getClass().getSimpleName());
2731    }
2732    eq FRealVariable.asFRealVariable() = this;
2733   
2734    syn FDerivativeVariable FAbstractVariable.asDerivativeVariable() {
2735        throw new UnsupportedOperationException("isDerivativeVariable() is not supported for class type " + getClass().getSimpleName());
2736    }
2737    eq FDerivativeVariable.asDerivativeVariable() = this;
2738
2739    syn boolean FAbstractVariable.isDummyDerivativeVariable() = false;
2740    eq FDummyDerivativeVariable.isDummyDerivativeVariable() = true;
2741
2742    syn boolean FAbstractVariable.isNonDummyDerivativeVariable()  = false;
2743    eq FAbstractDerivativeVariable.isNonDummyDerivativeVariable() = true;
2744    eq FDummyDerivativeVariable.isNonDummyDerivativeVariable()    = false;
2745
2746    syn boolean FAbstractVariable.isDynamicDerivativeVariable() = false;
2747    eq FDynamicDerivativeVariable.isDynamicDerivativeVariable() = true;
2748   
2749    syn boolean FAbstractVariable.isPreVariable() = false;
2750    eq FPreRealVariable.isPreVariable() = true;
2751    eq FPreIntegerVariable.isPreVariable() = true;
2752    eq FPreBooleanVariable.isPreVariable() = true;
2753    eq FPreStringVariable.isPreVariable() = true;
2754    eq FPreEnumVariable.isPreVariable() = true;
2755   
2756    syn boolean FAbstractVariable.isAlgebraicVariable() = false;
2757    syn boolean FVariable.isAlgebraicVariable()    = FClass.ALGEBRAIC_FILTER.testSingle(zCategory());
2758
2759    syn boolean FAbstractVariable.isDiscreteVariable() = false;
2760    syn boolean FVariable.isDiscreteVariable()    = zVariability() == FClass.ZVariability.DISCRETE;
2761
2762    syn boolean FAbstractVariable.isAlgebraicContinousRealVariable() = false;
2763    syn boolean FVariable.isAlgebraicContinousRealVariable()    = zCategory() == FClass.ZOrdinaryCategory.CONTINUOUS;
2764
2765    syn GUIDManager FClass.guidManager() = root().getUtilInterface().getGuidManager();
2766
2767    // TODO: This should be handled with a local map when needed, e.g. during
2768    // index reduction!
2769    @Deprecated
2770    private FVariable FVariable.meDifferentiated = null;
2771    @Deprecated
2772    private FVariable FVariable.meIntegrated = null;
2773
2774    @Deprecated
2775    public void FVariable.setMeDifferentiated(FVariable var) {
2776        this.meDifferentiated = var;
2777    }
2778
2779    /**
2780     * This method should only be used during index reduction where we can't
2781     * use variable lookup to resolve higher and lower order variables!
2782     * Instead, please use {@link #myDerivativeVariable()} instead!
2783     */
2784    @Deprecated
2785    public FVariable FVariable.getMeDifferentiated() {
2786        return this.meDifferentiated;
2787    }
2788
2789    @Deprecated
2790    public void FVariable.setMeIntegrated(FVariable var) {
2791        this.meIntegrated = var;
2792    }
2793
2794    /**
2795     * This method should only be used during index reduction where we can't
2796     * use variable lookup to resolve higher and lower order variables!
2797     * Instead, please use {@link #myDifferentiatedVariable()} instead!
2798     */
2799    @Deprecated
2800    public FVariable FVariable.getMeIntegrated() {
2801        return this.meIntegrated;
2802    }
2803
2804    @Deprecated
2805    public FVariable FVariable.getTopIntegrated() {
2806        FVariable fv = this;
2807        while (fv.meIntegrated != null)
2808            fv = fv.meIntegrated;
2809        return fv;
2810    }
2811
2812    // TODO: Unlike higher and lower order function on variables, this one
2813    // actually doesn't have any corresponding constructions, so we might
2814    // actually wan't to keep this functionality. However we should probably
2815    // move it to tokens or similar.
2816    @Deprecated
2817    private FAbstractEquation FAbstractEquation.meDifferentiated = null;
2818
2819    @Deprecated
2820    private FAbstractEquation FAbstractEquation.meIntegrated = null;
2821
2822    @Deprecated
2823    public void FAbstractEquation.setMeDifferentiated(FAbstractEquation e) {
2824        this.meDifferentiated = e;
2825    }
2826
2827    @Deprecated
2828    public FAbstractEquation FAbstractEquation.getMeDifferentiated() {
2829        return this.meDifferentiated;
2830    }
2831
2832    @Deprecated
2833    public void FAbstractEquation.setMeIntegrated(FAbstractEquation e) {
2834        this.meIntegrated = e;
2835    }
2836
2837    @Deprecated
2838    public FAbstractEquation FAbstractEquation.getMeIntegrated() {
2839        return this.meIntegrated;
2840    }
2841}
2842
2843aspect ReferencedVariables {
2844   
2845    public interface CommonAccessExpLookupVisitor<T extends CommonAccessExp> {
2846        public void visit(ASTNode<? extends ASTNode> node, Set<T> set);
2847        public abstract void add(CommonAccessExp access, Set<T> set);
2848    }
2849   
2850    public abstract class InstAccessExpLookupVisitor implements CommonAccessExpLookupVisitor<InstAccessExp> {
2851        @Override
2852        public void add(CommonAccessExp access, Set<InstAccessExp> set) {
2853            access.addToInstAccessExpSet(set);
2854        }
2855    }
2856
2857    public abstract class FAccessExpLookupVisitor implements CommonAccessExpLookupVisitor<FAccessExp> {
2858        @Override
2859        public void add(CommonAccessExp access, Set<FAccessExp> set) {
2860            access.addToFAccessExpSet(set);
2861        }
2862    }
2863
2864    public class DefaultInstAccessExpLookupVisitor extends InstAccessExpLookupVisitor {
2865        public static final DefaultInstAccessExpLookupVisitor instance = new DefaultInstAccessExpLookupVisitor();
2866       
2867        @Override
2868        public void visit(ASTNode<? extends ASTNode> node, Set<InstAccessExp> set) {
2869            node.findCommonAccessExpsInTree(set, this);
2870        }
2871    }
2872   
2873    public class DefaultFAccessExpLookupVisitor extends FAccessExpLookupVisitor {
2874        public static final DefaultFAccessExpLookupVisitor instance = new DefaultFAccessExpLookupVisitor();
2875       
2876        @Override
2877        public void visit(ASTNode<? extends ASTNode> node, Set<FAccessExp> set) {
2878            node.findCommonAccessExpsInTree(set, this);
2879        }
2880    }
2881   
2882    public void CommonAccessExp.addToInstAccessExpSet(Set<InstAccessExp> set) {}
2883    public void InstAccessExp.addToInstAccessExpSet(Set<InstAccessExp> set) {
2884        set.add(this);
2885    }
2886
2887    public void CommonAccessExp.addToFAccessExpSet(Set<FAccessExp> set) {}
2888    public void FAccessExp.addToFAccessExpSet(Set<FAccessExp> set) {
2889        set.add(this);
2890    }
2891
2892    public Set<InstAccessExp> ASTNode.findInstAccessExpsInTree() {
2893        return findCommonAccessExpsInTree(DefaultInstAccessExpLookupVisitor.instance);
2894    }
2895
2896    public Set<FAccessExp> ASTNode.findFAccessExpsInTree() {
2897        return findCommonAccessExpsInTree(DefaultFAccessExpLookupVisitor.instance);
2898    }
2899   
2900    public <T extends CommonAccessExp> Set<T> ASTNode.findCommonAccessExpsInTree(CommonAccessExpLookupVisitor<T> visitor) {
2901        Set<T> set = new LinkedHashSet<>();
2902        visitor.visit(this, set);
2903        return set;
2904    }
2905   
2906    public <T extends CommonAccessExp> void ASTNode.findCommonAccessExpsInTree(Set<T> set, CommonAccessExpLookupVisitor<T> visitor) {
2907        for (ASTNode n : this) {
2908            visitor.visit(n, set);
2909        }
2910    }
2911
2912    @Override
2913    public <T extends CommonAccessExp> void CommonAccessExp.findCommonAccessExpsInTree(Set<T> set, CommonAccessExpLookupVisitor<T> visitor) {
2914        visitor.add(this, set);
2915        super.findCommonAccessExpsInTree(set, visitor);
2916    }
2917
2918    @Override
2919    public <T extends CommonAccessExp> void FRelExp.findCommonAccessExpsInTree(Set<T> set, CommonAccessExpLookupVisitor<T> visitor) {
2920        if (!hasIndicator()) {
2921            super.findCommonAccessExpsInTree(set, visitor);
2922        } else {
2923            for (ASTNode<?> n : this) {
2924                if (n != getIndicatorOpt()) {
2925                    n.findCommonAccessExpsInTree(set, visitor);
2926                }
2927            }
2928        }
2929    }
2930
2931    @Override
2932    public <T extends CommonAccessExp> void FAttribute.findCommonAccessExpsInTree(Set<T> set, CommonAccessExpLookupVisitor<T> visitor) {
2933    }
2934
2935    syn Set<FAccessExp> FAbstractEquation.FAccessExpsInRHS() = FAccessExpsInRHS(DefaultFAccessExpLookupVisitor.instance);
2936
2937    syn Set<FAccessExp> FAbstractEquation.FAccessExpsInRHS(CommonAccessExpLookupVisitor<FAccessExp> visitor)
2938        = Collections.emptySet();
2939    eq FEquation.FAccessExpsInRHS(CommonAccessExpLookupVisitor<FAccessExp> visitor)
2940        = getRight().findCommonAccessExpsInTree(visitor);
2941    eq FFunctionCallEquation.FAccessExpsInRHS(CommonAccessExpLookupVisitor<FAccessExp> visitor)
2942        = getCall().findCommonAccessExpsInTree(visitor);
2943    eq FAlgorithm.FAccessExpsInRHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
2944        Set<FAccessExp> res = new LinkedHashSet<FAccessExp>();
2945        for (FStatement stmt : getFStatements())
2946            res.addAll(stmt.FAccessExpsInRHS(visitor));
2947        return res;
2948    }
2949
2950    syn Set<FAccessExp> FStatement.FAccessExpsInRHS() = FAccessExpsInRHS(DefaultFAccessExpLookupVisitor.instance);
2951
2952    syn Set<FAccessExp> FStatement.FAccessExpsInRHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
2953        Set<FAccessExp> res = new LinkedHashSet<>();
2954        for (FAccessExp use : findCommonAccessExpsInTree(visitor))
2955            if (!use.useIsAssignment() && !use.myFV().isForIndex())
2956                res.add(use);
2957        res.removeAll(FAccessExpsInLHS(visitor));
2958        return res;
2959    }
2960   
2961    eq FIfWhenElseEquation.FAccessExpsInRHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
2962        Set<FAccessExp> res = new LinkedHashSet<FAccessExp>();
2963        for (FAbstractEquation fae : getFAbstractEquations())
2964            res.addAll(fae.FAccessExpsInRHS(visitor));
2965        return res;
2966    }
2967   
2968    eq FIfWhenEquation.FAccessExpsInRHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
2969        Set<FAccessExp> res = super.FAccessExpsInRHS(visitor);
2970        getTest().findCommonAccessExpsInTree(res, visitor);
2971        if (hasElse())
2972            res.addAll(getElse().FAccessExpsInRHS(visitor));
2973        return res;
2974    }
2975   
2976    syn Set<FAccessExp> FAbstractEquation.FAccessExpsInLHS() = FAccessExpsInLHS(DefaultFAccessExpLookupVisitor.instance);
2977   
2978    syn Set<FAccessExp> FAbstractEquation.FAccessExpsInLHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) = Collections.emptySet();
2979    eq FEquation.FAccessExpsInLHS(CommonAccessExpLookupVisitor<FAccessExp> visitor)             = getLeft().findCommonAccessExpsInTree(visitor);
2980    eq FFunctionCallEquation.FAccessExpsInLHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) = getLefts().findCommonAccessExpsInTree(visitor);
2981    eq FAlgorithm.FAccessExpsInLHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
2982        Set<FAccessExp> res = new LinkedHashSet<FAccessExp>();
2983        for (FStatement stmt : getFStatements())
2984            res.addAll(stmt.FAccessExpsInLHS(visitor));
2985        return res;
2986    }
2987   
2988    syn Set<FAccessExp> FStatement.FAccessExpsInLHS() = FAccessExpsInLHS(DefaultFAccessExpLookupVisitor.instance);
2989   
2990    syn Set<FAccessExp> FStatement.FAccessExpsInLHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
2991        Set<FAccessExp> res = new LinkedHashSet<>();
2992        for (FAccessExp use : findCommonAccessExpsInTree(visitor))
2993            if (use.useIsAssignment() && !use.myFV().isForIndex())
2994                res.add(use);
2995        return res;
2996    }
2997   
2998    eq FIfWhenElseEquation.FAccessExpsInLHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
2999        Set<FAccessExp> res = new LinkedHashSet<FAccessExp>();
3000        for (FAbstractEquation fae : getFAbstractEquations())
3001            res.addAll(fae.FAccessExpsInLHS(visitor));
3002        return res;
3003    }
3004   
3005    eq FIfWhenEquation.FAccessExpsInLHS(CommonAccessExpLookupVisitor<FAccessExp> visitor) {
3006        Set<FAccessExp> res = super.FAccessExpsInLHS(visitor);
3007        if (hasElse())
3008            res.addAll(getElse().FAccessExpsInLHS(visitor));
3009        return res;
3010    }
3011   
3012    syn ArrayList<FAccessExp> FAbstractEquation.uniqueFAccessExpsInLHS() {
3013        ArrayList<FAccessExp>   res   = new ArrayList<>();
3014        Set<FAbstractVariable> visit = new LinkedHashSet<FAbstractVariable>();
3015        for (FAccessExp e : FAccessExpsInLHS()) {
3016            FAbstractVariable fv = e.myFV();
3017            if (!visit.contains(fv)) {
3018                visit.add(fv);
3019                res.add(e);
3020            }
3021        }
3022        return res;
3023    }
3024
3025    syn lazy Set<FAccessExp> FAbstractEquation.referencedCommonAccessExps() {
3026        Set<FAccessExp> res = new LinkedHashSet<>();
3027        res.addAll(FAccessExpsInLHS());
3028        res.addAll(FAccessExpsInRHS());
3029        return res;
3030    }
3031
3032    /***
3033     * DANGER! Use this method and its results with caution. It will probably
3034     * not work before saclarization but should be safe afterwards!
3035     */
3036    syn Set<String> FAbstractEquation.referencedVariablesAsStrings() {
3037        Set<FAccessExp> exps = new LinkedHashSet<FAccessExp>();
3038        Set<String> res = new LinkedHashSet<String>();
3039        for (FAccessExp exp : exps) {
3040            res.add(exp.name());
3041        }
3042        return res;
3043    }
3044    public static Set<FVariable> ASTNode.lookupFVariablesInSet(Set<FAccessExp> set) {
3045        Set<FVariable> res = new LinkedHashSet<FVariable>();
3046        for (FAccessExp use : set)
3047            if (use.myFV() instanceof FVariable)
3048                res.add((FVariable) use.myFV());
3049        return res;
3050    }
3051
3052    syn Set<FVariable> FAbstractEquation.variableDependenciesRHS() = referencedFVariablesInRHS();
3053    eq FAlgorithm.variableDependenciesRHS() {
3054        Set<FVariable> lhs = referencedFVariablesInLHS();
3055        Set<FVariable> rhs = referencedFVariablesInRHS();
3056        Set<FVariable> res = new LinkedHashSet<FVariable>();
3057        for (FVariable fv : rhs) {
3058            if (!lhs.contains(fv)) {
3059                res.add(fv);
3060            }
3061        }
3062        return res;
3063    }
3064   
3065    syn Set<FVariable> FAbstractEquation.referencedFVariablesInRHS() = lookupFVariablesInSet(FAccessExpsInRHS());
3066    syn Set<FVariable> FAbstractEquation.referencedFVariablesInLHS() = lookupFVariablesInSet(FAccessExpsInLHS());
3067    // Lazy is needed for FAlgorithms since the can have large number of scalars
3068    syn lazy Set<FVariable> FAlgorithm.referencedFVariablesInLHS() = super.referencedFVariablesInLHS();
3069    syn Set<FVariable> FExp.referencedFVariablesInFExp()             = lookupFVariablesInSet(findFAccessExpsInTree());
3070    syn Set<FVariable> FVariable.referencedFVariablesInBindingExp()  = lookupFVariablesInSet(getBindingExp().findFAccessExpsInTree());
3071    syn lazy Set<FVariable> FAbstractEquation.referencedFVariables() = lookupFVariablesInSet(referencedCommonAccessExps());
3072
3073    public static Set<FVariable> ASTNode.parametersInSet(Set<? extends FVariable> set) {
3074        Set<FVariable> res = new LinkedHashSet<FVariable>();
3075        for (FVariable fv : set)
3076            if (fv.isParameter())
3077                res.add(fv);
3078        return res;
3079    }
3080   
3081    syn Set<FVariable> FFunctionCallEquation.referencedParametersInLHS() = parametersInSet(referencedFVariablesInLHS());
3082    syn Set<FVariable> FExp.referencedParametersInFExp()                 = parametersInSet(referencedFVariablesInFExp());
3083
3084    syn boolean FAbstractEquation.assignedInAllBranches(FAbstractVariable var) = true;
3085    eq FEquation.assignedInAllBranches(FAbstractVariable var) = assignedInAllBranchesVariables().contains(var.name());
3086
3087    syn lazy Set<String> FEquation.assignedInAllBranchesVariables() {
3088        Set<String> res = new HashSet<String>();
3089        getLeft().assignedInAllBranchesVariables(res);
3090        getRight().assignedInAllBranchesVariables(res);
3091        return res;
3092    }
3093
3094    public final Set<String> FExp.assignedInAllBranchesVariables() {
3095        Set<String> res = new HashSet<String>();
3096        assignedInAllBranchesVariables(res);
3097        return res;
3098    }
3099
3100    public void FExp.assignedInAllBranchesVariables(Set<String> res) {
3101        for (FExp exp : childFExps())
3102            exp.assignedInAllBranchesVariables(res);
3103    }
3104
3105    @Override
3106    public void FAccessExp.assignedInAllBranchesVariables(Set<String> res) {
3107        res.add(name());
3108    }
3109
3110    @Override
3111    public void FIfExp.assignedInAllBranchesVariables(Set<String> res) {
3112        getIfExp().assignedInAllBranchesVariables(res);
3113        Set<String> a = getThenExp().assignedInAllBranchesVariables();
3114        Set<String> b = getElseExp().assignedInAllBranchesVariables();
3115        if (a.size() > b.size()) {
3116            Set<String> tmp = a;
3117            a = b;
3118            b = tmp;
3119        }
3120        for (String name : a) {
3121            if (b.contains(name)) {
3122                res.add(name);
3123            }
3124        }
3125    }
3126}
3127
3128
3129aspect FlatEnumerations {
3130   
3131    public ArrayList<FEnumLiteral> FEnumDecl.enumLiterals() {
3132        return getFEnumSpecification().enumLiterals();
3133    }
3134
3135    public ArrayList<FEnumLiteral> FEnumSpecification.enumLiterals() {
3136        return new ArrayList<FEnumLiteral>();
3137    }
3138
3139    public ArrayList<FEnumLiteral> FEnumLiteralList.enumLiterals() {
3140        ArrayList<FEnumLiteral> l = new ArrayList<FEnumLiteral>();
3141        for (FEnumLiteral el : getFEnumLiterals()) {
3142            l.add(el);
3143        }
3144        return l;
3145    }
3146   
3147    /**
3148     * The number of enumeration literals defined in the enumeration this variable is of.
3149     */
3150    syn int FEnumVariable.numEnumLiterals() = myFEnumDecl().numEnumLiterals();
3151   
3152    /**
3153     * The number of enumeration literals defined in this enumeration.
3154     */
3155    syn int FEnumDecl.numEnumLiterals() = getFEnumSpecification().numEnumLiterals();
3156   
3157    /**
3158     * The number of enumeration literals defined in this enumeration.
3159     */
3160    syn int FEnumSpecification.numEnumLiterals() = 0;
3161    eq FEnumLiteralList.numEnumLiterals() = getNumFEnumLiteral();
3162   
3163}
3164
3165aspect FlatCausality {
3166   
3167    syn boolean FAbstractVariable.isInput() = false;
3168    syn boolean FAbstractVariable.isOutput() = false;
3169    eq FVariable.isInput()          = getCausalityConnectorPrefix().inputCausality (this);
3170    eq FVariable.isOutput()         = getCausalityConnectorPrefix().outputCausality(this);
3171    eq FFunctionVariable.isInput()  = getCausalityConnectorPrefix().inputCausality (this);
3172    eq FFunctionVariable.isOutput() = getCausalityConnectorPrefix().outputCausality(this);
3173   
3174    ASTNode implements CausalPortsEvaluator;
3175    syn boolean ASTNode.useCausalPorts() = myOptions().causal_ports.getValue();
3176}
3177
3178aspect FlatTypes {
3179
3180    syn boolean FAbstractVariable.isReal()              = type().isReal();
3181    syn boolean FAbstractVariable.isInteger()           = type().isInteger();
3182    syn boolean FAbstractVariable.isBoolean()           = type().isBoolean();
3183    syn boolean FAbstractVariable.isString()            = type().isString();
3184    syn boolean FAbstractVariable.isRecord()            = type().isRecord();
3185    syn boolean FAbstractVariable.isEnum()              = type().isEnum();
3186    syn boolean FAbstractVariable.isExternalObject()    = type().isExternalObject();
3187   
3188    syn boolean FExp.isComposite()              = isArray() || type().isRecord();
3189    syn boolean FType.isComposite()             = isArray() || isRecord();
3190    syn boolean FAbstractVariable.isComposite() = isArray() || isRecord();
3191    syn boolean InstComponentDecl.isComposite() = isArray() || isRecord();
3192   
3193    inh boolean FAbstractVariable.inRecord();
3194    eq FRecordDecl.getChild().inRecord() = true;
3195    eq FClass.getChild().inRecord()      = false;
3196    eq FForIndex.getChild().inRecord()   = false;
3197
3198    inh boolean InstNode.inRecord();
3199    eq Root.getChild().inRecord()                               = false;
3200    eq InstClassDecl.getChild().inRecord()                      = false;
3201    eq InstForIndex.getInstPrimitive().inRecord()               = false;
3202    eq InstRecord.getChild().inRecord()                         = true;
3203    eq InstRecordConstructor.getChild().inRecord()              = true;
3204    eq InstArrayComponentDecl.getInstComponentDecl().inRecord() = inRecord();
3205    eq InstExtends.getInstComponentDecl().inRecord()            = inRecord();
3206
3207    inh boolean InstNode.inRecordDecl();
3208    eq Root.getChild().inRecordDecl()           = false;
3209    eq InstClassDecl.getChild().inRecordDecl()  = isRecord();
3210
3211    inh boolean InstComponentDecl.inRecordConstructor();
3212    inh boolean InstExtends.inRecordConstructor();
3213    eq InstRecordConstructor.getInstComponentDecl().inRecordConstructor() = true;
3214    eq InstRecordConstructor.getInstExtends().inRecordConstructor()       = true;
3215    eq InstExtends.getChild().inRecordConstructor()                       = inRecordConstructor();
3216    eq InstNode.getChild().inRecordConstructor()                          = false;
3217    eq Root.getChild().inRecordConstructor()                              = false;
3218
3219    syn int FRecordDecl.indexOf(String name) {
3220        for (int i = 0; i < getNumFVariable(); i++)
3221            if (getFVariable(i).name().equals(name))
3222                return i;
3223        return -1;
3224    }
3225   
3226    syn int FRecordDecl.indexOfArg(String name) {
3227        int k = 0;
3228        for (int i = 0; i < getNumFVariable(); i++) {
3229            if (getFVariable(i).modifiableInRecord) {
3230                if (getFVariable(i).name().equals(name))
3231                    return k;
3232                k++;
3233            }
3234        }
3235        return -1;
3236    }
3237   
3238    syn FExp FRecordDecl.extractArg(FRecordConstructor frc, String name) {
3239        return frc.getArg(indexOf(name));
3240    }
3241   
3242    inh FRecordDecl FExp.containingRecordDecl();
3243    inh FRecordDecl FAbstractVariable.containingRecordDecl();
3244    eq FRecordDecl.getChild().containingRecordDecl() = this;
3245    eq Root.getChild().containingRecordDecl()        = null;
3246
3247}
3248
3249
3250aspect Nominals {
3251    syn FExp FAbstractEquation.nominal() {
3252        FExp nom = FExp.nominalDefault();
3253        nom.setParent(this);
3254        return nom;
3255    }
3256    eq FEquation.nominal() {
3257        FExp nom = getLeft().dynamicFExp(FExp.nominalMax(getLeft(), getRight()));
3258        if (nom.variability().knownParameterOrLess()) {
3259            try {
3260                CValue val = nom.ceval();
3261                if (val.hasBuildLiteral()) {
3262                    nom = getLeft().dynamicFExp(val.buildLiteral());
3263                }
3264            } catch (ConstantEvaluationException e) {}
3265        }
3266        return nom;
3267    }
3268   
3269    public static FExp FExp.nominalMax(FExp e1, FExp e2) {
3270        return new FMaxExp(e1.nominal(), new Opt<FExp>(e2.nominal()));
3271    }
3272    public static FExp FExp.nominalDefault() {
3273        return new FIntegerLitExp(1);
3274    }
3275   
3276    syn FExp FExp.nominal() = FExp.nominalDefault();
3277    eq FLitExp.nominal()    = new FAbsExp(fullCopy());
3278   
3279    eq FDotAddExp.nominal() = FExp.nominalMax(getLeft(), getRight());
3280    eq FDotSubExp.nominal() = FExp.nominalMax(getLeft(), getRight());
3281    eq FDotMulExp.nominal() = new FMulExp(getLeft().nominal(), getRight().nominal());
3282    eq FDotDivExp.nominal() = new FDivExp(getLeft().nominal(), getRight().nominal());
3283    eq FNegExp.nominal()    = getFExp().nominal();
3284    eq FAbsExp.nominal()    = getFExp().nominal();
3285    eq FMinMaxExp.nominal() = hasY() ? FExp.nominalMax(getX(), getY()) : getX().nominal();
3286   
3287    eq FIfExp.nominal()     = FExp.nominalMax(getThenExp(), getElseExp());
3288   
3289    eq FNoEventExp.nominal() = getFExp().nominal();
3290    eq FSmoothExp.nominal()  = getFExp().nominal();
3291   
3292    eq FHomotopyExp.nominal()    = FExp.nominalMax(getActual(), getSimplified());
3293    eq FSpatialDistExp.nominal() = FExp.nominalMax(getIn0(), getIn1());
3294    eq FDelayExp.nominal()       = getFExp().nominal();
3295   
3296    eq FAccessExp.nominal() = myFV().nominal();
3297    eq FGlobalAccessExp.nominal() = new FAbsExp(treeCopy());
3298   
3299    syn FExp FAbstractVariable.nominal() {
3300        if (variability().fixedParameterOrLess()) {
3301            return new FAbsExp(createAccessExp());
3302        } else {
3303            return variableNominal();
3304        }
3305    }
3306    eq UnknownFVariable.nominal() = variableNominal();
3307   
3308    syn FExp FAbstractVariable.variableNominal() {
3309        return FExp.nominalDefault();
3310    }
3311   
3312    eq FRealVariable.variableNominal() {
3313        if (nominalAttributeSet()) {
3314            return new FAbsExp(nominalAttributeExp().unboundCopy());
3315        } else {
3316            return super.variableNominal();
3317        }
3318    }
3319}
3320
3321aspect FVariableUses {
3322   
3323    /**
3324     * Collection attribute returning all variable uses in expressions.
3325     */
3326    coll HashSet<FAccessExp> FAbstractVariable.uses() [new LinkedHashSet<>()] 
3327        with add root FClass;
3328   
3329    FAccessExp contributes this to FAbstractVariable.uses() for myFV();
3330   
3331    /**
3332     * All uses of this variable that are not the left-hand side of an equation.
3333     * (Unless the variable has a binding expression, then this is the same as uses().)
3334     */
3335    syn lazy Set<FAccessExp> FAbstractVariable.nonDefiningUses() {
3336        Set<FAccessExp> res = new HashSet<FAccessExp>();
3337        for (FAccessExp use : uses())
3338            if (hasBindingExp() || !use.isLeftHandSide())
3339                res.add(use);
3340        return res;
3341    }
3342   
3343    /**
3344     * All uses of this variable that are the left-hand side of an equation.
3345     * (Unless the variable has a binding expression, then this is empty.)
3346     */
3347    syn lazy Set<FAccessExp> FAbstractVariable.definingUses() {
3348        if (hasBindingExp()) {
3349            return Collections.emptySet();
3350        } else {
3351            Set<FAccessExp> res = new HashSet<FAccessExp>();
3352            for (FAccessExp use : uses())
3353                if (use.isLeftHandSide())
3354                    res.add(use);
3355            return res;
3356        }
3357    }
3358   
3359    inh boolean FExp.inFunctionCallLeft();
3360    eq FFunctionCallLeft.getChild().inFunctionCallLeft() = true;
3361    eq FClass.getChild().inFunctionCallLeft()            = false;
3362    eq InstRoot.getChild().inFunctionCallLeft()          = false;
3363   
3364    inh boolean FExp.isFunctionCallLeft();
3365    eq FFunctionCallLeft.getChild().isFunctionCallLeft() = true;
3366    eq FExp.getChild().isFunctionCallLeft()              = false;
3367    eq FClass.getChild().isFunctionCallLeft()            = false;
3368    eq InstRoot.getChild().isFunctionCallLeft()          = false;
3369   
3370    /**
3371     * Checks if this expression is used in a function call
3372     */
3373    inh boolean FExp.inFunctionCall();
3374    eq FFunctionCall.getChild().inFunctionCall() = true;
3375    eq FClass.getChild().inFunctionCall()        = false;
3376    eq InstRoot.getChild().inFunctionCall()      = false;
3377   
3378    inh boolean FExp.isFunctionCallArg();
3379    eq BaseNode.getChild().isFunctionCallArg()    = false;
3380    eq FFunctionCall.getArg().isFunctionCallArg() = true;
3381    eq FIfExp.getThenExp().isFunctionCallArg()    = isFunctionCallArg();
3382    eq FIfExp.getElseExp().isFunctionCallArg()    = isFunctionCallArg();
3383
3384    syn boolean FExp.containsCommonFunctionCallExp() {
3385        for (FExp exp : childFExps()) {
3386            if (exp.containsCommonFunctionCallExp()) {
3387                return true;
3388            }
3389        }
3390        return false;
3391    }
3392    eq CommonFunctionCall.containsCommonFunctionCallExp() = true;
3393
3394    /**
3395     * Returnes the function input that this expressions corresponds to.
3396     * NOTICE, this method will throw exception if this exp does not reside in a function call.
3397     */
3398    inh CommonVariableDecl FExp.myCorrespondingInput();
3399    eq FFunctionCall.getArg(int i).myCorrespondingInput()    = myFCallable().myInput(i);
3400    eq InstFunctionCall.getArg(int i).myCorrespondingInput() = myInstCallable().myCallInputs().get(i);
3401    eq FClass.getChild().myCorrespondingInput() {
3402        throw new UnsupportedOperationException();
3403    }
3404    eq InstRoot.getChild().myCorrespondingInput() {
3405        throw new UnsupportedOperationException();
3406    }
3407   
3408    /**
3409     * Check if this is the left hand side of an equation.
3410     */
3411    inh boolean FExp.isLeftHandSide();
3412    eq BaseNode.getChild().isLeftHandSide()    = false;
3413    eq FEquation.getLeft().isLeftHandSide()    = true;
3414    eq FFunctionCallLeft.getChild().isLeftHandSide()  = true;
3415    eq FArray.getChild().isLeftHandSide()             = isLeftHandSide();
3416    eq FRecordConstructor.getChild().isLeftHandSide() = isLeftHandSide();
3417   
3418    /**
3419     * Check if this is the left hand side of an assignment or function call statement.
3420     */
3421    inh boolean FAssignableExp.isAssignedTo();
3422    inh boolean FFunctionCallLeft.isAssignedTo();
3423    eq BaseNode.getChild().isAssignedTo()         = false;
3424    eq FAssignStmt.getLeft().isAssignedTo()       = true;
3425    eq FFunctionCallStmt.getLeft().isAssignedTo() = true;
3426    eq FFunctionCallLeft.getFExp().isAssignedTo() = isAssignedTo();
3427   
3428    /**
3429     * Check if this is exp is bound in a declaration
3430     */
3431    inh boolean FExp.isBound();
3432    eq Root.getChild().isBound()                   = false;
3433    eq InstValueModification.getFExp().isBound()   = true;
3434    eq InstFunctionCall.getArg().isBound()        = false;
3435   
3436    inh boolean FExp.inParamBindingExp();
3437    eq Root.getChild().inParamBindingExp() = false;
3438    eq FVariable.getBindingExp().inParamBindingExp() = isParameter();
3439   
3440    inh TypePrefixVariability FExp.bindingExpVariability();
3441    eq Root.getChild().bindingExpVariability() = Variability.CONTINUOUS;
3442    eq FVariable.getChild().bindingExpVariability() = variability();
3443    eq FVariable.getFAttribute().bindingExpVariability() = Variability.FIXEDPARAMETER;
3444    eq FRecordVariable.getFAttribute(int i).bindingExpVariability() =
3445            variability().component(getFAttribute(i).name());
3446   
3447    /**
3448     * Collection attribute returning all dependent parameters which
3449     * depends on the parameter.
3450     */
3451   
3452    coll HashSet<FVariable> FAbstractVariable.dependentParameters() 
3453      [new LinkedHashSet<FVariable>()] 
3454        with addAll root FlatRoot;
3455   
3456    FAccessExp contributes boundParameters() when myFV().isParameter()
3457        to FAbstractVariable.dependentParameters() for myFV();
3458   
3459    syn lazy Collection<FRealVariable> FAbstractVariable.dependentRealParameters() =
3460            FClass.filterCollection(dependentParameters(), FClass.REAL_VARIABLE_FILTER);
3461
3462    syn lazy Collection<FIntegerVariable> FAbstractVariable.dependentIntegerParameters() =
3463            FClass.filterCollection(dependentParameters(), FClass.INTEGER_VARIABLE_FILTER);
3464
3465    syn lazy Collection<FEnumVariable> FAbstractVariable.dependentEnumParameters() =
3466            FClass.filterCollection(dependentParameters(), FClass.ENUM_VARIABLE_FILTER);
3467   
3468    syn lazy Collection<FBooleanVariable> FAbstractVariable.dependentBooleanParameters() =
3469            FClass.filterCollection(dependentParameters(), FClass.BOOLEAN_VARIABLE_FILTER);
3470
3471    syn lazy Collection<FStringVariable> FAbstractVariable.dependentStringParameters() =
3472            FClass.filterCollection(dependentParameters(), FClass.STRING_VARIABLE_FILTER);
3473
3474    /**
3475     * Collection attribute returning all input variables (FVariables)
3476     * referenced in an equation.
3477     */
3478     
3479    coll LinkedHashSet<FVariable> FAbstractEquation.retrieveInputs() 
3480        [new LinkedHashSet<FVariable>()] with add root FAbstractEquation;
3481
3482    FAccessExp contributes (FVariable) myFV() when
3483        myFV().isFVariable() && myFV().isInput() to
3484        FAbstractEquation.retrieveInputs() for myFEquation();
3485
3486    syn lazy LinkedHashSet<FVariable> FAbstractEquation.inputs() = 
3487        retrieveInputs();
3488   
3489    eq FIfWhenElseEquation.inputs()  {
3490        LinkedHashSet<FVariable> s = new LinkedHashSet<FVariable>();
3491        s.addAll(retrieveInputs());
3492        for (FAbstractEquation e : getFAbstractEquations()) {
3493            s.addAll(e.inputs());
3494        }
3495        return s;
3496    }
3497    eq FIfWhenEquation.inputs()  {
3498        LinkedHashSet<FVariable> s = new LinkedHashSet<FVariable>();
3499        s.addAll(super.inputs());
3500        if (hasElse())
3501            s.addAll(getElse().inputs());
3502        return s;
3503    }
3504
3505    syn lazy LinkedHashSet<FVariable> FAbstractEquation.realInputs() = 
3506            new LinkedHashSet<FVariable>(FClass.filterCollection(inputs(), FClass.REAL_VARIABLE_FILTER));
3507
3508   
3509    /**
3510     * Collection attribute returning all algebraic variables (FVariables)
3511     * referenced in an equation.
3512     */
3513    coll LinkedHashSet<FVariable> FAbstractEquation.algebraicVariables() 
3514        [new LinkedHashSet<FVariable>()] with add root FAbstractEquation;
3515
3516    FAccessExp contributes (FVariable) myFV() when isAlgebraicVariableAccess() to
3517        FAbstractEquation.algebraicVariables() for each enclosingEquationsIterator();
3518
3519    syn boolean FAccessExp.isAlgebraicVariableAccess() = inAccessLocation() && myFV().isAlgebraicVariable();
3520
3521    /**
3522     * Returns true if this access is in a location where it should be
3523     * contributed to the equation system.
3524     */
3525    inh boolean FAccessExp.inAccessLocation();
3526    eq FlatRoot.getChild().inAccessLocation()               = false;
3527    eq SourceRoot.getChild().inAccessLocation()             = false;
3528    eq FAbstractEquation.getFAttribute().inAccessLocation() = false;
3529    eq FAbstractEquation.getChild().inAccessLocation()      = true;
3530    eq FRelExp.getIndicator().inAccessLocation()            = false;
3531
3532
3533    /**
3534     * Collection attribute returning all derivative variables (FDerivativeVariables)
3535     * referenced in an equation.
3536     */
3537    coll LinkedHashSet<FDerivativeVariable> FAbstractEquation.derivativeVariables() 
3538        [new LinkedHashSet<FDerivativeVariable>()] with add root FAbstractEquation;
3539
3540    FDerExp contributes (FDerivativeVariable) myFV() when myFV().isDerivativeVariable() && inAccessLocation() to
3541        FAbstractEquation.derivativeVariables() for each enclosingEquationsIterator();
3542
3543    /**
3544     * Collection attribute returning all differentiated variables (FVariables)
3545     * referenced in an equation.
3546     */
3547    coll LinkedHashSet<FVariable> FAbstractEquation.differentiatedRealVariables() 
3548        [new LinkedHashSet<FVariable>()] with add root FAbstractEquation;
3549
3550    FAccessExp contributes (FVariable) myFV() when myFV().isDifferentiatedVariable() && inAccessLocation() to
3551        FAbstractEquation.differentiatedRealVariables() for each enclosingEquationsIterator();
3552
3553    /**
3554     * Collection attribute returning all dependent parameter variables (FVariables)
3555     * referenced in an equation.
3556     */
3557    coll LinkedHashSet<FVariable> FAbstractEquation.parameters() 
3558        [new LinkedHashSet<FVariable>()] with add root FAbstractEquation;
3559
3560    FAccessExp contributes (FVariable) myFV() when myFV().isParameter() && inAccessLocation() to
3561        FAbstractEquation.parameters() for each enclosingEquationsIterator();
3562
3563    /**
3564     * Collection attribute returning all discrete variables (FVariables)
3565     * referenced in an equation.
3566     */
3567    coll LinkedHashSet<FVariable> FAbstractEquation.discreteVariables() 
3568        [new LinkedHashSet<FVariable>()] with add root FAbstractEquation;
3569
3570    FAccessExp contributes (FVariable) myFV() when myFV().isDiscreteVariable() && inAccessLocation() to
3571        FAbstractEquation.discreteVariables() for each enclosingEquationsIterator();
3572
3573    /**
3574     * Collection attribute returning all non-fixed parameters (FVariables)
3575     * referenced in an equation.
3576     */
3577    coll LinkedHashSet<FVariable> FAbstractEquation.initialParameters()
3578        [new LinkedHashSet<FVariable>()] with add root FAbstractEquation;
3579
3580    FAccessExp contributes (FVariable) myFV() when myFV().isInitialParameter() && inAccessLocation() to
3581        FAbstractEquation.initialParameters() for each enclosingEquationsIterator();
3582
3583    /**
3584     * Collection attribute returning all pre variables (FPreVariable)
3585     * referenced in an equation.
3586     */
3587    coll LinkedHashSet<FVariable> FAbstractEquation.discretePreVariables() 
3588        [new LinkedHashSet<FVariable>()] with add root FAbstractEquation;
3589
3590    FPreExp contributes (FVariable) myFV() when myFV().isPreVariable() && inAccessLocation() to
3591        FAbstractEquation.discretePreVariables() for each enclosingEquationsIterator();
3592
3593    syn lazy LinkedHashSet<FVariable> FAbstractEquation.variables() {
3594        LinkedHashSet<FVariable> l = new LinkedHashSet<FVariable>();
3595        l.addAll(differentiatedRealVariables());
3596        l.addAll(derivativeVariables());
3597        l.addAll(algebraicVariables());
3598        l.addAll(discreteVariables());
3599        return l;
3600    }
3601
3602    /**
3603     * Returns the event indicators for the expressions that are found by {@link #relExpInEquation}.
3604     */
3605    syn Set<FVariable> FAbstractEquation.eventIndicators() {
3606        Set<EventGeneratingExp> exps = new HashSet<>();
3607        exps.addAll(relExpInEquation());
3608        exps.addAll(delayExpInEquation());
3609        exps.addAll(spatialDistExpInEquation());
3610       
3611        Set<FVariable> res = new HashSet<>();
3612        for (EventGeneratingExp exp : exps) {
3613            if (exp.hasIndicator()) {
3614                res.addAll(exp.myIndicatorVariables());
3615            }
3616        }
3617        return res;
3618    }
3619
3620    /**
3621     * Returns all variables known to this equation that are part of the
3622     * equation system, e.g. variables in the attributes isn't included in this
3623     * list.
3624     * <p>
3625     * Word of causion, this method is used for debug output right now and I
3626     * got a feeling that it might return the same variable twice! So test well
3627     * if you're going to use it "for real".
3628     */
3629    syn Iterable<FVariable> FAbstractEquation.allVariables() {
3630        return new ChainedIterable<FVariable>(variables(), discretePreVariables(), parameters());
3631    }
3632
3633    /**
3634     * Get the differenetiated variabel (FVariable) corresponding to
3635     * a derivative variable (FDerivativeVariable)
3636     */
3637    syn FAbstractVariable FVariable.myDifferentiatedVariable() {
3638        if (order() <= 0) {
3639            return unknownFVariable();
3640        } else if (order() == 1) {
3641            return getFAccess().myFV();
3642        } else {
3643            return getFAccess().myDerFV(order() - 1);
3644        }
3645    }
3646
3647    /**
3648     * Get the derivative variabel (FDerivativeVariable) corresponding to
3649     * a differentiated variable (FVariable)
3650     */
3651    syn FAbstractVariable FVariable.myDerivativeVariable() = getFAccess().myDerFV(order() + 1);
3652
3653    /**
3654     * Get the pre variable connected to a normal variable, if any.
3655     */
3656    syn FAbstractVariable FAbstractVariable.myPreVariable() = getFAccess().myPreFV();
3657   
3658    /**
3659     * Get the normal variable connected to a pre variable.
3660     *
3661     * Will be unknown for non-pre variables.
3662     */
3663    syn FAbstractVariable FAbstractVariable.myNonPreVariable() = getFAccess().myFV();
3664}
3665
3666aspect LinearFVariables {
3667   
3668    /**
3669     * Check linearity of variable.
3670     *
3671     * The attribute isLinear returns true if all uses of the variable appears
3672     * linearly in equations and in initial equations. Parameters and constants
3673     * are assumed to be literals in the linearity computation. Accordingly,
3674     * multiplication of a variable with a parameter or constant does not render
3675     * the variable nonlinear. Also, parameters and constants are considered
3676     * to be linear themselves.
3677     */
3678    syn lazy boolean FVariable.isLinear() {
3679        if (isParameter() || isConstant()) {
3680            return true;
3681        }
3682        for (FAccessExp e : uses()) {
3683            if (!e.isLinear()) {
3684                return false;
3685            }
3686        }
3687        return true;
3688    }
3689   
3690    /**
3691     * Check if a subexpression appears linearly.
3692     *
3693     * Note that this method does not check if the expression itself is linear
3694     * but wheather it apperas linearly in a composite expression. For example
3695     * the sub expression 'sin(x)' appears linearly in '1+sin(x)'.
3696     */
3697    inh boolean FExp.isLinear();
3698    eq FlatRoot.getChild().isLinear() = true;
3699    eq SourceRoot.getChild().isLinear() = true;
3700   
3701    eq FAbstractEquation.getChild().isLinear() = true;
3702   
3703    eq FDotMulExp.getLeft().isLinear() =
3704        (getRight().isConstantExp() || getRight().isLinearParameterExp())?
3705                isLinear() : false;
3706    eq FDotMulExp.getRight().isLinear() =
3707        (getLeft().isConstantExp() || getLeft().isLinearParameterExp())?
3708                isLinear() : false;
3709    eq FDotDivExp.getLeft().isLinear() =
3710        (getRight().isConstantExp() || getRight().isLinearParameterExp())?
3711                isLinear() : false;
3712    eq FDotDivExp.getRight().isLinear() = false;
3713    eq FDotPowExp.getChild().isLinear() = false;
3714    eq FFunctionCall.getChild().isLinear() = false;
3715    eq FMathematicalFunctionCall.getChild().isLinear() = false;
3716               
3717    // This definition is to avoid errors when isParameterExp is redefined
3718    // to include free parameters in the Optimica extension.
3719    syn boolean FExp.isLinearParameterExp() = isParameterExp();
3720   
3721    syn boolean FAbstractEquation.checkLinearity(Set<FVariable> vars) {
3722        for (FAccessExp e : referencedCommonAccessExps()) {
3723            if (vars.contains(e.myFV()) && !e.isLinear(vars)) {
3724                return false;
3725            }
3726        }
3727        return true;
3728    }
3729    eq FIfWhenElseEquation.checkLinearity(Set<FVariable> vars) = false;
3730    eq FAlgorithm.checkLinearity(Set<FVariable> vars) = false;
3731   
3732    inh boolean FExp.isLinear(Set<FVariable> vars);
3733    eq FlatRoot.getChild().isLinear(Set<FVariable> vars)   = true;
3734    eq SourceRoot.getChild().isLinear(Set<FVariable> vars) = true;
3735   
3736    eq FAbstractEquation.getChild().isLinear(Set<FVariable> vars) = true;
3737    eq FStatement.getChild().isLinear(Set<FVariable> vars)        = false;
3738   
3739    eq FDotMulExp.getLeft().isLinear(Set<FVariable> vars)  = getRight().isIndependent(vars) && isLinear(vars);
3740    eq FDotMulExp.getRight().isLinear(Set<FVariable> vars) = getLeft().isIndependent(vars) && isLinear(vars);
3741    eq FDotDivExp.getLeft().isLinear(Set<FVariable> vars)  = getRight().isIndependent(vars) && isLinear(vars);
3742    eq FDotDivExp.getRight().isLinear(Set<FVariable> vars) = false;
3743    eq FDotPowExp.getChild().isLinear(Set<FVariable> vars) = false;
3744    eq FFunctionCall.getChild().isLinear(Set<FVariable> vars) = false;
3745    eq FMathematicalFunctionCall.getChild().isLinear(Set<FVariable> vars) = false;
3746    eq FAbstractFunctionCall.getChild().isLinear(Set<FVariable> vars) = false;
3747    eq FIfExp.getIfExp().isLinear(Set<FVariable> vars) = !isWhen() && (!inNoEventExp() || getIfExp().isIndependent(vars)); 
3748    eq FNoEventExp.getFExp().isLinear(Set<FVariable> vars) = isLinear(vars);
3749   
3750    syn boolean FExp.isIndependent(Set<? extends CommonVariableDecl> set) {
3751        for (FExp e : childFExps()) {
3752            if (!e.isIndependent(set)) {
3753                return false;
3754            }
3755        }
3756        return true;
3757    }
3758
3759    syn boolean FIfExp.isIndependent(Set<? extends CommonVariableDecl> set) {
3760        // Don't check the guard exp since it is discrete and does not affect
3761        // linearity.
3762        return getThenExp().isIndependent(set) && getElseExp().isIndependent(set);
3763    }
3764
3765    eq FAbstractDerExp.isIndependent(Set<? extends CommonVariableDecl> set) {
3766        return !set.contains(myFV());
3767    }
3768
3769    eq FAccessExp.isIndependent(Set<? extends CommonVariableDecl> set) {
3770        return getFAccess().isIndependent(set);
3771    }
3772
3773    syn boolean CommonAccess.isIndependent(Set<? extends CommonVariableDecl> set);
3774   
3775    eq FAccess.isIndependent(Set<? extends CommonVariableDecl> set) {
3776        return !set.contains(myFV());
3777    }
3778
3779    eq InstAccess.isIndependent(Set<? extends CommonVariableDecl> set) {
3780        return !set.contains(myInstComponentDecl());
3781    }
3782
3783}
3784
3785aspect FlatDiagnostics {
3786
3787    syn String FClass.diagnostics() {
3788        StringBuilder str = new StringBuilder();
3789        str.append("Diagnostics for flattened class " + name() + "\n");
3790
3791        str.append(modelDiagnostics());
3792       
3793        str.append("\n");
3794       
3795        str.append(variableDiagnostics());
3796       
3797        str.append("\n"); 
3798
3799        str.append(aliasDiagnostics());
3800       
3801        str.append("\n"); 
3802       
3803        str.append(incidence());
3804
3805        str.append("\n"); 
3806       
3807        str.append(dependencyDiagnostics());
3808
3809        str.append("\n");
3810       
3811//      str.append(dersAndDiffs());
3812       
3813        str.append("\n"); 
3814       
3815        str.append(connectionSetDiagnostics());
3816       
3817        return str.toString();
3818    }
3819
3820    public String FClass.modelDiagnostics() {
3821        StringBuilder str = new StringBuilder();
3822        modelDiagnosticsPrintRow(str, "Number of independent constants:", independentConstants());
3823        modelDiagnosticsPrintRow(str, "  Number of Real independent constants:", independentRealConstants());
3824        modelDiagnosticsPrintRow(str, "  Number of Real independent constants:", independentRealConstants());
3825        modelDiagnosticsPrintRow(str, "  Number of Integer independent constants:", independentIntegerConstants());
3826        modelDiagnosticsPrintRow(str, "  Number of Enum independent constants:", independentEnumConstants());
3827        modelDiagnosticsPrintRow(str, "  Number of Boolean independent constants:", independentBooleanConstants());
3828        modelDiagnosticsPrintRow(str, "  Number of String independent constants:", independentStringConstants());
3829
3830        modelDiagnosticsPrintRow(str, "Number of dependent constants:", dependentConstants());
3831        modelDiagnosticsPrintRow(str, "  Number of Real dependent constants:", dependentRealConstants());
3832        modelDiagnosticsPrintRow(str, "  Number of Integer dependent constants:", dependentIntegerConstants());
3833        modelDiagnosticsPrintRow(str, "  Number of Enum dependent constants:", dependentEnumConstants());
3834        modelDiagnosticsPrintRow(str, "  Number of Boolean dependent constants:", dependentBooleanConstants());
3835        modelDiagnosticsPrintRow(str, "  Number of String dependent constants:", dependentStringConstants());
3836
3837        modelDiagnosticsPrintRow(str, "Number of independent parameters:", independentParameters());
3838        modelDiagnosticsPrintRow(str, "  Number of Real independent parameters:", independentRealParameters());
3839        modelDiagnosticsPrintRow(str, "  Number of Integer independent parameters:", independentIntegerParameters());
3840        modelDiagnosticsPrintRow(str, "  Number of Enum independent parameters:", independentEnumParameters());
3841        modelDiagnosticsPrintRow(str, "  Number of Boolean independent parameters:", independentBooleanParameters());
3842        modelDiagnosticsPrintRow(str, "  Number of String independent parameters:", independentStringParameters());
3843                 
3844        modelDiagnosticsPrintRow(str, "Number of dependent parameters:", dependentParameters());
3845        modelDiagnosticsPrintRow(str, "  Number of Real dependent parameters:", dependentRealParameters());
3846        modelDiagnosticsPrintRow(str, "  Number of Integer dependent parameters:", dependentIntegerParameters());
3847        modelDiagnosticsPrintRow(str, "  Number of Enum dependent parameters:", dependentEnumParameters());
3848        modelDiagnosticsPrintRow(str, "  Number of Boolean dependent parameters:", dependentBooleanParameters());
3849        modelDiagnosticsPrintRow(str, "  Number of String dependent parameters:", dependentStringParameters());
3850       
3851        modelDiagnosticsPrintRow(str, "Number of initial parameters:", initialParameters());
3852        modelDiagnosticsPrintRow(str, "  Number of Real dependent parameters:", realInitialParameters());
3853        modelDiagnosticsPrintRow(str, "  Number of Integer dependent parameters:", integerInitialParameters());
3854        modelDiagnosticsPrintRow(str, "  Number of Enum dependent parameters:", enumInitialParameters());
3855        modelDiagnosticsPrintRow(str, "  Number of Boolean dependent parameters:", booleanInitialParameters());
3856        modelDiagnosticsPrintRow(str, "  Number of String dependent parameters:", stringInitialParameters());
3857       
3858        modelDiagnosticsPrintRow(str, "Number of variables:", variables());
3859        modelDiagnosticsPrintRow(str, "  Number of Real variables:", realVariables());
3860        modelDiagnosticsPrintRow(str, "  Number of Integer variables:", integerVariables());
3861        modelDiagnosticsPrintRow(str, "  Number of Enum variables:", enumVariables());
3862        modelDiagnosticsPrintRow(str, "  Number of Boolean variables:", booleanVariables());
3863        modelDiagnosticsPrintRow(str, "  Number of String variables:", stringVariables());
3864
3865        modelDiagnosticsPrintRow(str, "Number of Real differentiated variables:", differentiatedRealVariables()); 
3866        modelDiagnosticsPrintRow(str, "Number of Real derivative variables:", derivativeVariables()); 
3867        modelDiagnosticsPrintRow(str, "Number of Real continous algebraic variables:", algebraicContinousRealVariables());
3868
3869        modelDiagnosticsPrintRow(str, "Number of inputs:", inputs());
3870        modelDiagnosticsPrintRow(str, "  Number of Real inputs:", realInputs());
3871        modelDiagnosticsPrintRow(str, "  Number of Integer inputs:", integerInputs());
3872        modelDiagnosticsPrintRow(str, "  Number of Enum inputs:", enumInputs());
3873        modelDiagnosticsPrintRow(str, "  Number of Boolean inputs:", booleanInputs());
3874        modelDiagnosticsPrintRow(str, "  Number of String inputs:", stringInputs());
3875       
3876        modelDiagnosticsPrintRow(str, "Number of discrete variables:", discreteVariables());
3877        modelDiagnosticsPrintRow(str, "  Number of Real discrete variables:", discreteRealVariables());
3878        modelDiagnosticsPrintRow(str, "  Number of Integer discrete variables:", discreteIntegerVariables());
3879        modelDiagnosticsPrintRow(str, "  Number of Enum discrete variables:", discreteEnumVariables());
3880        modelDiagnosticsPrintRow(str, "  Number of Boolean discrete variables:", discreteBooleanVariables());
3881        modelDiagnosticsPrintRow(str, "  Number of String discrete variables:", discreteStringVariables());
3882       
3883        modelDiagnosticsPrintRow(str, "Number of equations:", equations());
3884       
3885        modelDiagnosticsPrintRow(str, "Number of variables with binding expression:", variablesWithBindingExp());
3886        modelDiagnosticsPrintRow(str, "  Number of Real variables with binding exp:", realVariablesWithBindingExp());
3887        modelDiagnosticsPrintRow(str, "  Number of Integer variables binding exp:", integerVariablesWithBindingExp());
3888        modelDiagnosticsPrintRow(str, "  Number of Enum variables binding exp:", enumVariablesWithBindingExp());
3889        modelDiagnosticsPrintRow(str, "  Number of Boolean variables binding exp:", booleanVariablesWithBindingExp());
3890        modelDiagnosticsPrintRow(str, "  Number of String variables binding exp:", stringVariablesWithBindingExp());
3891           
3892        modelDiagnosticsPrintRow(str, "Total number of equations:", equations(), variablesWithBindingExp());
3893   
3894        modelDiagnosticsPrintRow(str, "Number of initial equations:", initialEquations());
3895
3896        str.append(String.format("Number of event indicators in equations:      %6d\n", numEventIndicators()));
3897        str.append(String.format("Number of event indicators in init equations: %6d\n", numRelExpInInitialEquations()));
3898
3899
3900        return str.toString();
3901    }
3902   
3903    private static void FClass.modelDiagnosticsPrintRow(StringBuilder sb, String label, Collection<? extends FDiagnosticsNode> ... lists) {
3904        int num = 0;
3905        int numScalar = 0;
3906        for (Collection<? extends FDiagnosticsNode> list : lists) {
3907            num += list.size();
3908            numScalar += countNumScalars(list);
3909        }
3910        sb.append(String.format("%-46s%6d(%5d scalars)\n", label, num, numScalar));
3911    }
3912
3913    private static int FClass.countNumScalars(Collection<? extends FDiagnosticsNode> nodes) {
3914        int num = 0;
3915        for (FDiagnosticsNode node : nodes)
3916            num += node.numScalars();
3917        return num;
3918    }
3919
3920    public interface FDiagnosticsNode {
3921        public int numScalars();
3922    }
3923    public class FAbstractEquation implements FDiagnosticsNode {}
3924    public class FVariable implements FDiagnosticsNode {}
3925   
3926    syn int FAbstractEquation.numScalars() = numScalarEquations();
3927    syn int FVariable.numScalars() = type().numScalarElements();
3928   
3929    public String FClass.aliasDiagnostics() {
3930        StringBuilder str = new StringBuilder();
3931        str.append("Alias sets:\n");
3932        if (getAliasManager()!=null) {
3933            str.append(getAliasManager());
3934            int n_elim = 0;
3935            for (AliasManager.AliasSet aliasSet : getAliasManager().getAliasSets()) {
3936                n_elim += aliasSet.numAliases() - 1;
3937            }
3938            str.append(n_elim + " variables can be eliminated\n");
3939               
3940        } else {
3941            str.append("  Alias sets not computed.\n");
3942        }
3943        return str.toString(); 
3944       
3945    }
3946
3947    public String FClass.aliasDiagnosticsShort() {
3948        StringBuilder str = new StringBuilder();
3949        if (getAliasManager()!=null) {
3950            int n_elim = 0;
3951            Set<AliasManager.AliasSet> aliasSets = getAliasManager().getAliasSets();
3952            for (AliasManager.AliasSet aliasSet : aliasSets) {
3953                n_elim += aliasSet.numAliases() - 1;
3954            }
3955            str.append(aliasSets.size());
3956            str.append(" sets, ");
3957            str.append(n_elim);
3958            str.append(" eliminated variables");
3959        } else {
3960            str.append("Alias sets not computed");
3961        }
3962        return str.toString(); 
3963       
3964    }
3965
3966    public String FClass.variableDiagnostics() {
3967       
3968        StringBuilder str = new StringBuilder();
3969       
3970        str.append("Independent constants: \n");
3971        for (FVariable fv : independentConstants()) {
3972            str.append(" " + fv.name());
3973            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
3974                    + fv.isLinear());
3975                str.append("\n");
3976        }
3977        str.append("\n");
3978       
3979        str.append("Dependent constants: \n");
3980        for (FVariable fv : dependentConstants()) {
3981            str.append(" " + fv.name());
3982            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
3983                    + fv.isLinear());
3984                str.append("\n");
3985        }
3986        str.append("\n");
3987       
3988        str.append("Independent parameters: \n");
3989        for (FVariable fv : independentParameters()) {
3990            str.append(" " + fv.name());
3991            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
3992                    + fv.isLinear());
3993            if (fv.hasBindingExp()) {
3994                CValue val = CValue.UNKNOWN;
3995                try {
3996                    val = fv.getBindingExp().ceval();
3997                } catch (ConstantEvaluationException e) {
3998                   
3999                }
4000                str.append(", evaluated binding exp: ");
4001                str.append(val);
4002            }
4003            str.append("\n");
4004        }
4005        str.append("\n");
4006       
4007        str.append("Dependent parameters: \n");
4008        for (FVariable fv : dependentParameters()) {
4009            str.append(" " + fv.name());
4010            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
4011                    + fv.isLinear());
4012                str.append("\n");
4013        }
4014
4015        str.append("\n"); 
4016        str.append("Differentiated variables: \n");
4017        for (FVariable fv : differentiatedRealVariables()) {
4018            str.append(" " + fv.name());
4019            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
4020                    + fv.isLinear());
4021            str.append("\n");
4022        }
4023
4024        str.append("\n"); 
4025        str.append("Derivative variables: \n");
4026        for (FVariable fv : derivativeVariables()) {
4027            str.append(" " + fv.name());
4028            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
4029                    + fv.isLinear());
4030                str.append("\n");
4031        }
4032        str.append("\n"); 
4033
4034        str.append("Discrete variables: \n");
4035        for (FVariable fv : discreteVariables()) {
4036            str.append(" " + fv.name());
4037            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
4038                    + fv.isLinear());
4039            str.append(", alias: ");
4040            if (!fv.isAlias()) {
4041                str.append("no");
4042            } else {
4043                if (fv.isNegated()) {
4044                    str.append("-");
4045                }
4046                str.append(fv.alias().valueReference());
4047            }
4048            str.append("\n");
4049        }
4050        str.append("\n");
4051       
4052        str.append("Algebraic real variables: \n");
4053        for (FVariable fv : algebraicContinousRealVariables()) {
4054            str.append(" " + fv.name());
4055            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
4056                    + fv.isLinear());
4057            str.append(", alias: ");
4058            if (!fv.isAlias()) {
4059                str.append("no");
4060            } else {
4061                if (fv.isNegated()) {
4062                    str.append("-");
4063                }
4064                str.append(fv.alias().valueReference());
4065            }
4066            str.append("\n");
4067        }
4068        str.append("\n");
4069       
4070        str.append("Input variables: \n");
4071        for (FVariable fv : inputs()) {
4072            str.append(" " + fv.name());
4073            str.append(": number of uses: " + fv.uses().size() + ", isLinear: " 
4074                    + fv.isLinear());
4075                str.append("\n");
4076        }
4077
4078        return str.toString();
4079       
4080    }
4081
4082    public String FClass.dependencyDiagnostics() {
4083       
4084        StringBuilder str = new StringBuilder();
4085           
4086        if (myOptions().getBooleanOption("equation_sorting")) {
4087           
4088            str.append("Variable dependencies:\n");
4089           
4090            if (getNumFVariable() > myOptions().getIntegerOption("diagnostics_limit")) {
4091                str.append("Oh dear, the model has way to many variables (" + getNumFVariable() + ")!\n");
4092                str.append("Current limit is set to " + myOptions().getIntegerOption("diagnostics_limit") + ", you can change this by changing the option 'diagnostics_limit'.\n");
4093                return str.toString();
4094            }
4095           
4096            str.append("Derivative variables: \n");
4097            for (FVariable fv : derivativeVariables()) {
4098                str.append(" " + fv.name() + "\n");
4099                for (FVariable d : fv.dependsOn()) {
4100                    str.append("    " + d.name() + "\n");
4101                }
4102            }
4103            str.append("\n");
4104            str.append("Differentiated variables: \n");
4105            for (FVariable fv : differentiatedRealVariables()) {
4106                str.append(" " + fv.name() + "\n");
4107                for (FVariable d : fv.dependsOn()) {
4108                    str.append("    " + d.name() + "\n");
4109                }
4110            }
4111            str.append("\n");
4112            str.append("Algebraic real variables: \n");
4113            for (FVariable fv : algebraicContinousRealVariables()) {
4114                str.append(" " + fv.name() + "\n");
4115                for (FVariable d : fv.dependsOn()) {
4116                    str.append("    " + d.name() + "\n");
4117                }
4118            }
4119            str.append("\n");
4120        }
4121        return str.toString();
4122    }
4123   
4124    public String FClass.directDependencyDiagnostics() {
4125        StringBuilder sb = new StringBuilder();
4126        for (FVariable output : realOutputs()) {
4127            sb.append(output.name());
4128            sb.append("\n");
4129            for (FVariable input : output.directDependencies()) {
4130                sb.append("    ");
4131                sb.append(input.name());
4132                sb.append("\n");
4133            }
4134        }
4135        return sb.toString();
4136    }   
4137   
4138    public Set<FVariable> FVariable.directDependencies() {
4139        Set<FVariable> res = new LinkedHashSet<FVariable>();
4140        for (FVariable dv : dependsOn()) {
4141            if (dv.isInput()) {
4142                res.add(dv);
4143            }
4144        }
4145        return res;
4146    }
4147
4148    public String FClass.connectionSetDiagnostics() {
4149        return getConnectionSetManager().printConnectionSets();
4150    }
4151   
4152    public String FClass.incidence() {
4153        return incidence(false);
4154    }
4155
4156    public String FClass.incidence(boolean printAllVariables) {
4157        StringBuilder str = new StringBuilder();
4158       
4159        str.append("Incidence:\n");
4160       
4161        int i = 0;
4162        for (FAbstractEquation fe : equations()) {
4163            Iterable<? extends FVariable> vars;
4164            if (printAllVariables) {
4165                vars = fe.allVariables();
4166            } else {
4167                vars = new ChainedIterable<FVariable>(fe.derivativeVariables(), fe.algebraicVariables());
4168            }
4169            str.append(" eq " + i + ":");
4170            for (FVariable var : vars) {
4171                str.append(" " + var.name());
4172            }
4173            str.append("\n");
4174            i++;
4175        }
4176       
4177        return str.toString();
4178    }
4179   
4180    public String FClass.dersAndDiffs() {
4181        StringBuilder str = new StringBuilder();
4182        str.append("Derivatives and differentiated variables:\n");
4183        for (FDerivativeVariable fdv : derivativeVariables()) {
4184            if (fdv.myDifferentiatedVariable()!=null) {
4185                str.append(" " + fdv.name() + ", " + fdv.myDifferentiatedVariable().name() + "\n");
4186            }
4187        }   
4188        str.append("Differentiated variables and derivatives:\n");
4189        for (FVariable fv : differentiatedRealVariables()) {
4190            if (fv.myDerivativeVariable()!=null) {
4191                str.append(" " + fv.name() + ", " + fv.myDerivativeVariable().name() + "\n");
4192            }
4193        }
4194        return str.toString();
4195       
4196    }
4197   
4198    public String FClass.printDAEBLT() {
4199        return getDAEBLT() == null ? "" : getDAEBLT().toString();
4200    }
4201
4202    public String FClass.printDAEInitBLT() {
4203        return getDAEInitBLT().toString();
4204    }
4205   
4206    public String FClass.printMatchedDAE() {
4207        return computeMatchedDAEBiPGraph(createBLTInput()).toString();
4208    }
4209
4210
4211    syn String FClass.attributeLevels() {
4212        StringBuilder str = new StringBuilder();
4213        str.append("Variables:\n");
4214        for (FVariable v : getFVariables())
4215            v.attributeLevels(str);
4216        for (FVariable v : getAliasVariables())
4217            v.attributeLevels(str);
4218        if (getNumFDerivedType() > 0) {
4219            str.append("\nTypes:\n");
4220            for (FDerivedType t : getFDerivedTypes())
4221                t.attributeLevels(str);
4222        }
4223        return str.toString();
4224    }
4225
4226    public void FVariable.attributeLevels(StringBuilder str) {
4227        str.append("  ");
4228        str.append(name());
4229        attributeLevelsForList(getFAttributes(), str);
4230        str.append("\n");
4231    }
4232
4233    public void FDerivedType.attributeLevels(StringBuilder str) {
4234        str.append("  ");
4235        str.append(getName());
4236        attributeLevelsForList(getFAttributes(), str);
4237        str.append("\n");
4238    }
4239
4240    public void FAttribute.attributeLevels(StringBuilder str) {
4241        str.append(name());
4242        str.append(":");
4243        str.append(getLevel());
4244        attributeLevelsForList(getFAttributes(), str);
4245        if (hasValue()) {
4246            str.append("=");
4247            str.append(getValue());
4248        }
4249    }
4250
4251    public static void ASTNode.attributeLevelsForList(List<FAttribute> l, StringBuilder str) {
4252        if (l.getNumChild() > 0) {
4253            str.append("(");
4254            String sep = ", ";
4255            String pref = "";
4256            for (FAttribute a : l) {
4257                str.append(pref);
4258                a.attributeLevels(str);
4259                pref = sep;
4260            }
4261            str.append(")");
4262        }
4263    }
4264
4265}
4266
4267aspect FlatAlgorithmAPI {
4268   
4269    syn boolean FExp.inFAlgorithm() = myFAlgorithm() != null;
4270   
4271    syn FAlgorithm FAccessExp.myFAlgorithm() = getFAccess().myFAlgorithm();
4272    inh lazy FAlgorithm CommonAccess.myFAlgorithm();
4273    inh lazy FAlgorithm FStatement.myFAlgorithm();
4274    inh FAlgorithm FExp.myFAlgorithm();
4275    eq FAbstractEquation.getChild().myFAlgorithm() = null;
4276    eq FAlgorithm.getChild().myFAlgorithm() = this;
4277    eq Root.getChild().myFAlgorithm() = null;
4278   
4279    coll ArrayList<FAlgorithm> FClass.myAlgorithms()
4280        [new ArrayList<FAlgorithm>()] with add root FClass;
4281    FAlgorithm contributes this when !inFunction()
4282        to FClass.myAlgorithms() for myFClass();
4283   
4284    inh boolean CommonAccess.useIsAssignment();
4285    inh boolean FAssignableExp.useIsAssignment();
4286    inh boolean FArray.useIsAssignment();
4287    inh boolean FRecordConstructor.useIsAssignment();
4288    eq FAssignStmt.getLeft().useIsAssignment()       = true;
4289    eq FFunctionCallLeft.getFExp().useIsAssignment() = true;
4290    eq FAssignableExp.getChild().useIsAssignment()   = useIsAssignment();
4291    eq FArraySubscripts.getChild().useIsAssignment() = false;
4292    eq FArray.getFExp().useIsAssignment()            = useIsAssignment();
4293    eq FRecordConstructor.getArg().useIsAssignment() = useIsAssignment();
4294    eq FExp.getChild().useIsAssignment()             = false;
4295    eq FStatement.getChild().useIsAssignment()       = false;
4296    eq FAlgorithm.getChild().useIsAssignment()       = false;
4297    eq Root.getChild().useIsAssignment()             = false;
4298   
4299    private String FAlgorithm.functionName = null;
4300    public String FAlgorithm.generateFunctionName() {
4301        if (functionName == null)
4302            functionName = myFClass().generateFunctionName();
4303        return functionName;
4304    }
4305    private int FClass.generatedFunctionNumber = 1;
4306    public String FClass.generateFunctionName() {
4307        String name, part;
4308        do {
4309            part = "algorithm_" + generatedFunctionNumber;
4310            name = name() + "." + part;
4311            generatedFunctionNumber++;
4312        } while (lookupFunc(name) != null || variablesMap().lookup(part) != null);
4313        return name;
4314    }
4315   
4316}
4317
4318aspect FlatExternalFunctionAPI {
4319   
4320    /**
4321     * Gives the arguments to pass to gcc required by external functions.
4322     */
4323    syn String FClass.externalCompilerArgs() {
4324        StringBuilder buf = new StringBuilder();
4325        for (String lib : externalLibraries()) {
4326            buf.append(" -l");
4327            buf.append(lib);
4328        }
4329        for (String dir : externalLibraryDirectories()) {
4330            buf.append(" -L");
4331            buf.append(dir);
4332        }
4333        for (String dir : externalIncludeDirectories()) {
4334            buf.append(" -I");
4335            buf.append(dir);
4336        }
4337        return buf.toString();
4338    }
4339
4340    syn String FClass.externalLibArgs() {
4341        StringBuilder buf = new StringBuilder();
4342        for (String lib : externalLibraries()) {
4343            buf.append(" -l");
4344            buf.append(lib);
4345        }
4346        for (String dir : externalLibraryDirectories()) {
4347            buf.append(" -L");
4348            buf.append(dir);
4349        }
4350        return buf.toString();
4351    }
4352
4353    syn String FClass.externalIncludeArgs() {
4354        StringBuilder buf = new StringBuilder();
4355        for (String dir : externalIncludeDirectories()) {
4356            buf.append(" -I");
4357            buf.append(dir);
4358        }
4359        return buf.toString();
4360    }
4361   
4362    coll HashSet<FExternalStmt> FClass.myExternals()
4363        [new LinkedHashSet<FExternalStmt>()] with add root FClass;
4364    FExternalStmt contributes this
4365        to FClass.myExternals() for myFClass();
4366   
4367    syn HashSet<String> FClass.externalLibraries() {
4368        HashSet<String> res = new LinkedHashSet<String>();
4369        for (FExternalStmt ext : myExternals())
4370            if (ext.library() != null)
4371                for (String lib : ext.library())
4372                    res.add(lib);
4373        return res;
4374    }
4375   
4376    syn HashSet<String> FClass.externalIncludes() {
4377        HashSet<String> res = new LinkedHashSet<String>();
4378        for (FExternalStmt ext : myExternals())
4379            if (ext.include() != null)
4380                res.add(ext.include());
4381        return res;
4382    }
4383   
4384    syn HashSet<String> FClass.externalLibraryDirectories() {
4385        HashSet<String> res = new LinkedHashSet<String>();
4386        for (FExternalStmt ext : myExternals())
4387            if (ext.libraryDirectory() != null)
4388                res.add(ext.libraryDirectory());
4389        return res;
4390    }
4391   
4392    syn HashSet<String> FClass.externalIncludeDirectories() {
4393        HashSet<String> res = new LinkedHashSet<String>();
4394        for (FExternalStmt ext : myExternals())
4395            if (ext.includeDirectory() != null)
4396                res.add(ext.includeDirectory());
4397        return res;
4398    }
4399   
4400    syn String[] FExternalStmt.library() = library;
4401    syn String FExternalStmt.include()            = include;
4402    syn String FExternalStmt.libraryDirectory()   = libraryDir;
4403    syn String FExternalStmt.includeDirectory()   = includeDir;
4404    syn boolean FExternalStmt.isIncluded() = !(include() == null || include().equals(""));
4405    syn boolean FExternalStmt.isInLibrary() = !(libraryDirectory() == null || libraryDirectory().equals(""));
4406   
4407    private String[] FExternalStmt.library;
4408    private String FExternalStmt.include;
4409    private String FExternalStmt.libraryDir;
4410    private String FExternalStmt.includeDir;
4411   
4412    public void FExternalStmt.extractLibrary(FExternalStmt n) {
4413        this.library = n.library;
4414        this.include = n.include;
4415        this.libraryDir = n.libraryDir;
4416        this.includeDir = n.includeDir;
4417    }
4418   
4419    public void FExternalStmt.extractLibrary(InstExternal n) {
4420        library = n.annotation("Library").asStringVector();
4421        include = n.annotation("Include").string();
4422        libraryDir = n.annotation("LibraryDirectory").string();
4423        includeDir = n.annotation("IncludeDirectory").string();
4424       
4425        if (libraryDir == null || includeDir == null) {
4426            String libraryName = n.libraryName();
4427            if (libraryName != null) {
4428                String defDir = "modelica://" + libraryName + "/Resources";
4429                libraryDir = (libraryDir == null && library != null) ? 
4430                        defDir + "/Library" : libraryDir;
4431                includeDir = (includeDir == null && include != null) ? 
4432                        defDir + "/Include" : includeDir;
4433            }
4434        }
4435       
4436        if (includeDir != null) 
4437            includeDir = URIResolver.DEFAULT.resolve(n, includeDir);
4438        if (libraryDir != null) {
4439            libraryDir = URIResolver.DEFAULT.resolve(n, libraryDir);
4440        }
4441    }
4442
4443}
4444
4445aspect ExpressionGeneralisation {
4446    /**
4447     * Returns the expression stripped of any negations
4448     */
4449    syn FExp FExp.stripNegations()     = this;
4450    eq FNegExp.stripNegations()        = getFExp().stripNegations();
4451   
4452   
4453    syn boolean FEquation.isNegated() = getLeft().isNegated() ^ getRight().isNegated();
4454   
4455    /**
4456     * Check if the expressions is negated
4457     */
4458    syn boolean FExp.isNegated()  = false;
4459    eq FNegExp.isNegated()        = !getFExp().isNegated();
4460   
4461    /**
4462     * Return this expression negated if <code>neg</code> is true.
4463     */
4464    syn FExp FExp.negated(boolean neg) {
4465        if (neg)
4466            return new FNegExp(unboundCopy());
4467        else
4468            return unboundCopy();
4469    }
4470
4471    /**
4472     * The format string including the implicit leading "%", if the format argument is given.
4473     */
4474    syn lazy Opt<FExp> FStringExp.getCFormatOpt() {
4475        // TODO: To save memory, this could be solved in the C code generation instead.
4476        if (hasFormat()) {
4477            FExp fmt = getFormat();
4478            FExp exp = fmt.treeCopy();
4479            boolean initialPercent = false;
4480            try {
4481                initialPercent = formatSpecifier().initialPercent;
4482            } catch (ConstantEvaluationException e) {
4483                // If we can't evaluate it here, assume there is no "%"
4484            }
4485            if (!initialPercent) {
4486                exp = new FStringAddExp(new FStringLitExp("%"), exp);
4487            }
4488            if (fmt.variability().fixedParameterOrLess()) {
4489                try {
4490                    exp.parent = this;
4491                    exp = exp.ceval().buildLiteral();
4492                } catch (ConstantEvaluationException e) {
4493                    // If we can't evaluate, just leave it as is
4494                }
4495            }
4496            return new Opt<FExp>(exp);
4497        } else {
4498            return new Opt<FExp>();
4499        }
4500    }
4501}
Note: See TracBrowser for help on using the repository browser.