source: branches/dev-cw-2613/Compiler/ModelicaFrontEnd/src/jastadd/util/Util.jrag @ 13841

Last change on this file since 13841 was 13841, checked in by Christian Andersson, 6 weeks ago

Merged latest changes from trunk into the branch. Related to ticket:5863

File size: 72.8 KB
Line 
1/*
2    Copyright (C) 2009-2017 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
17
18import java.util.Collection;
19import java.util.HashSet;
20import java.util.HashMap;
21import java.util.Iterator;
22import java.util.Map;
23import java.util.ArrayList;
24import java.util.LinkedHashSet;
25import java.util.NoSuchElementException;
26import java.util.regex.Matcher;
27import java.util.regex.Pattern;
28import java.io.File;
29import java.io.FileInputStream;
30import java.io.FileNotFoundException;
31import java.io.InputStreamReader;
32import java.io.PrintStream;
33import java.io.Reader;
34import java.io.UnsupportedEncodingException;
35import java.nio.file.Files;
36import java.nio.file.StandardCopyOption;
37import java.net.URI;
38import java.net.URISyntaxException;
39import java.nio.charset.Charset;
40
41import org.jmodelica.util.formatting.FormattingRecorder;
42import org.jmodelica.util.formatting.DefaultFormattingRecorder;
43import org.jmodelica.util.logging.StreamingLogger;
44import org.jmodelica.util.logging.Level;
45import org.jmodelica.util.AbstractModelicaScanner;
46import org.jmodelica.util.collections.ChainedIterable;
47import org.jmodelica.util.collections.TransformerIterable;
48
49import org.jmodelica.common.URIResolver;
50
51aspect RootAccess {
52
53    syn String SourceRoot.language() = "Modelica";
54    public static String ASTNode.JMODELICA_VENDOR_NAME = "JModelica.org";
55    public static String ASTNode.vendorName() {
56        return ASTNode.JMODELICA_VENDOR_NAME;
57    }
58
59    inh Root ASTNode.retrieveRoot();
60    eq Root.getChild().retrieveRoot() = this;
61    syn Root ASTNode.root()  = retrieveRoot();
62    syn Root BaseNode.root() = retrieveRoot();
63    eq Root.root()           = this;
64
65    syn SourceRoot InstNode.sourceRoot() = (SourceRoot) root();
66
67    // TODO: When uses of ArrayList has been generalised to List, replace with Collections.emptyList()
68    public static final ArrayList ASTNode.EMPTY_ARRAY_LIST = new ArrayList(0);
69    syn ArrayList ASTNode.emptyArrayList() = EMPTY_ARRAY_LIST;
70
71    public boolean ASTNode.hasRoot() { return (getParent() == null) ? false : getParent().hasRoot(); }
72    public boolean Root.hasRoot()    { return true; }
73
74}
75
76aspect Logging {
77
78    public static ModelicaLogger ASTNode.log = ModelicaCompiler.log;
79   
80}
81
82aspect NodeMethods {
83
84    /**
85     * Implementing {@link ASTNode#iterator()} is required as of JastAdd 2.2.0.
86     */
87    public class ASTNode<T extends ASTNode> implements Iterable<T> {
88        @Override
89        public Iterator<T> iterator() {
90            return astChildIterator();
91        }
92    }
93
94    public class ASTNode {
95        /**
96         * Copies the member variables defining the location within
97         *        the source to another node.
98         *       
99         * @param n  the node to copy the location to
100         * @return   the node given as <code>n</code>, for convenience
101         */
102        public <N extends ASTNode> N copyLocationTo(N n) {
103            n.setLocation(this, this);
104            return n;
105        }
106    }
107   
108    /**
109     * Sets the member variables defining the location of the node within
110     *        the source to values copied another node.
111     */
112    public void ASTNode.setLocation(ASTNode node) {
113            setLocation(node, node);
114    }
115   
116    /**
117     * Sets the member variables defining the location of the node within
118     *        the source to values copied from two other nodes.
119     *
120     * @param start  the node to copy the <code>start</code> member from.
121     * @param end    the node to copy the <code>end</code> member from.
122     */
123    public void ASTNode.setLocation(ASTNode start, ASTNode end) {
124        this.start = start.start;
125        this.end = end.end;
126    }
127   
128    /**
129     * Sets the member variables defining the location of the node within
130     *        the source to values copied from two other nodes.
131     *
132     * @param start  the node to copy the <code>start</code> and <code>fName</code>
133     *               members from.
134     * @param end    the node to copy the <code>end</code> member from.
135     */
136    public void BaseNode.setLocation(ASTNode start, ASTNode end) {
137        super.setLocation(start, end);       
138        fName = start.fileNames();
139    }
140   
141    /**
142     * Sets the member variables defining the location of the node within
143     *        the source to values copied another node, that might not be in a
144     *        proper AST.
145     */
146    public void ASTNode.setLocationNoTree(ASTNode node) {
147            setLocationNoTree(node, node);
148    }
149   
150    /**
151     * Sets the member variables defining the location of the node within
152     *        the source to values copied from two other nodes, that might not be
153     *        in a proper AST.
154     *
155     * @param start  the node to copy the <code>start</code> member from.
156     * @param end    the node to copy the <code>end</code> member from.
157     */
158    public void ASTNode.setLocationNoTree(ASTNode start, ASTNode end) {
159        setLocation(start, end);
160    }
161   
162    /**
163     * Sets the member variables defining the location of the node within
164     *        the source to values copied from two other parser symbols,
165     *        that might not be AST nodes.
166     *
167     * @param start  the node to copy the <code>start</code> member from.
168     * @param end    the node to copy the <code>end</code> member from.
169     */
170    public void ASTNode.setLocationNoTree(Symbol start, Symbol end) {
171        this.start = start.getStart();
172        this.end = end.getEnd();
173    }
174   
175    /**
176     * Sets the member variables defining the location of the node within
177     *        the source to values copied from two other nodes, that might not be
178     *        in a proper AST.
179     *
180     * @param start  the node to copy the <code>start</code> and <code>fName</code>
181     *               members from.
182     * @param end    the node to copy the <code>end</code> member from.
183     */
184    public void BaseNode.setLocationNoTree(ASTNode start, ASTNode end) {
185        setLocationNoTree(start, end, start);
186    }
187   
188    /**
189     * Sets the member variables defining the location of the node within
190     *        the source to values copied from two other nodes, that might not be
191     *        in a proper AST.
192     * @param start      the node to copy the <code>start</code> member from.
193     * @param end        the node to copy the <code>end</code> member from.
194     * @param fNameNode  the node to copy the <code>fName</code> member from.
195     */
196    public void BaseNode.setLocationNoTree(ASTNode start, ASTNode end, ASTNode fNameNode) {
197        super.setLocation(start, end);
198        if (fNameNode instanceof BaseNode)
199                fName = ((BaseNode) fNameNode).fName;
200    }
201   
202    protected <T extends ASTNode> T ASTNode.setLocationOf(T node) {
203        node.setLocationNoTree(this);
204        return node;
205    }
206   
207    protected void BaseNode.addLocation(ASTNode node){
208        int l1 = 0;
209        int l2 = 0;
210        SourceLocation[] sourceA, sourceA2;
211        if(node == null)
212                return;
213        if(fName == null || !(node instanceof BaseNode)){
214                setLocationNoTree(node);
215                return;
216        }
217        BaseNode sourceNode = (BaseNode)node; 
218        if(fName instanceof String){
219                l1 = 1;
220                sourceA = new SourceLocation[1];
221                sourceA[0] = new SourceLocation((String)fName, start, end);
222        }else{
223                l1 = ((SourceLocation[])fName).length;
224                sourceA = ((SourceLocation[])fName);
225        }
226        if(sourceNode.fName == null){
227                return;
228        }else if(sourceNode.fName instanceof String){
229                l2 = 1;
230                sourceA2 = new SourceLocation[1];
231                sourceA2[0] = new SourceLocation((String)sourceNode.fName, sourceNode.start, sourceNode.end);
232        }else{
233                l2 = ((SourceLocation[])sourceNode.fName).length;
234                sourceA2 = ((SourceLocation[])sourceNode.fName).clone();
235        }
236       
237        ArrayList<SourceLocation> tempLocations = new ArrayList<SourceLocation>();
238        for(int i = 0; i < l1; i++){
239                boolean ignoreSourceA = false; 
240                        for(int j = 0; j < l2; j++){
241                                if(sourceA2[j] == null){
242                                        continue;
243                                }
244                                if(sourceA[i].locationContainedBy(sourceA2[j])){
245                                        tempLocations.add(sourceA2[j]);
246                                        sourceA2[j] = null;
247                                        ignoreSourceA = true;
248                                }
249                                else if(!sourceA2[j].locationContainedBy(sourceA[i])){
250                                        tempLocations.add(sourceA2[j]);
251                                        sourceA2[j] = null;
252                                }
253                        }
254                        if(!ignoreSourceA)
255                                tempLocations.add(sourceA[i]);
256                }
257        if(tempLocations.size() == 1){
258                fName = tempLocations.get(0).getFile();
259                start = tempLocations.get(0).getStart();
260                end = tempLocations.get(0).getEnd();
261        }else{
262                fName = tempLocations.toArray(sourceA);                 
263        }
264       
265    }
266   
267   
268    syn boolean BaseNode.locationContainedBy() {
269        if(!(fName instanceof String))
270                return false;
271        BaseNode parentWithLocation = parentWithLocation();
272        if (parentWithLocation == null) {
273                return false;
274        }
275                return fName.equals(parentWithLocation.fName) && start >= parentWithLocation.start && end <= parentWithLocation.end;           
276    }
277    inh BaseNode BaseNode.parentWithLocation();
278    eq BaseNode.getChild().parentWithLocation() {
279        if (fName != null) {
280                return this;
281        } else {
282                return parentWithLocation();
283        }
284    }
285    eq Root.getChild().parentWithLocation() = null;
286
287   
288    public boolean SourceLocation.locationContainedBy(SourceLocation location){
289        if(fName == null || location.fName == null)
290                return false;
291        if(fName.equals(location.fName) && start >= location.start && end <= location.end){
292                        return true;
293                }
294        return false;
295    }
296   
297   
298    public void FExp.collectLocations(BaseNode collector){
299                return;
300        }
301   
302    public void FEquation.collectLocations(BaseNode collector){
303        collector.addLocation(this);
304                getLeft().collectLocations(collector);
305                getRight().collectLocations(collector);
306                return;
307        }
308   
309        public void FUnaryExp.collectLocations(BaseNode collector){
310                collector.addLocation(this);
311                getFExp().collectLocations(collector);
312        }
313       
314        public void FBinExp.collectLocations(BaseNode collector){
315                collector.addLocation(this);
316                getLeft().collectLocations(collector);
317                getRight().collectLocations(collector);
318        }
319       
320        public void FLitExp.collectLocations(BaseNode collector){
321                collector.addLocation(this);
322        }
323       
324        public void FAccessExp.collectLocations(BaseNode collector){
325                FAbstractVariable fv = myFV();
326                if(fv.hasBindingExp()){
327                collector.addLocation(((FVariable)fv).getBindingExp());
328        }
329        }
330
331    /**
332     * Returns the starting line for this node, or zero if positional
333     * information is unavailable.
334     */
335    syn int ASTNode.beginLine()   = getLine(getStart());
336    /**
337     * Returns the starting column for this node, or zero if positional
338     * information is unavailable.
339     */
340    syn int ASTNode.beginColumn() = getColumn(getStart());
341    /**
342     * Returns the ending line for this node, or zero if positional
343     * information is unavailable.
344     */
345    syn int ASTNode.endLine()     = getLine(getEnd());
346    /**
347     * Returns the ending column for this node, or zero if positional
348     * information is unavailable.
349     */
350    syn int ASTNode.endColumn()   = getColumn(getEnd());
351
352    /**
353     * Returns the starting line for this node, or if unavailable, will make a
354     * recursive call to the parent and ask for its starting line. Zero is
355     * returned if positional information is unavailable for this node and its
356     * parents.
357     */
358    syn int ASTNode.beginLineRecursive() = (start != 0 || getParent() == null)
359            ? beginLine() : getParent().beginLineRecursive();
360    /**
361     * Returns the starting column for this node, or if unavailable, will make
362     * a recursive call to the parent and ask for its starting column. Zero is
363     * returned if positional information is unavailable for this node and its
364     * parents.
365     */
366    syn int ASTNode.beginColumnRecursive() = (start != 0 || getParent() == null)
367            ? beginColumn() : getParent().beginColumnRecursive();
368    /**
369     * Returns the ending line for this node, or if unavailable, will make a
370     * recursive call to the parent and ask for its ending line. Zero is
371     * returned if positional information is unavailable for this node and its
372     * parents.
373     */
374    syn int ASTNode.endLineRecursive() = (end != 0 || getParent() == null)
375            ? endLine() : getParent().endLineRecursive();
376    /**
377     * Returns the ending column for this node, or if unavailable, will make a
378     * recursive call to the parent and ask for its ending column. Zero is
379     * returned if positional information is unavailable for this node and its
380     * parents.
381     */
382    syn int ASTNode.endColumnRecursive() = (end != 0 || getParent() == null)
383            ? endColumn() : getParent().endColumnRecursive();
384
385    public class List {
386
387            /**
388             * Creates a new ArrayList containing all the elements in this list, in the same order.
389             */
390            public ArrayList<T> toArrayList() {
391                ArrayList<T> l = new ArrayList<T>(getNumChild());
392                for (T e : this)
393                    l.add(e);
394                return l;
395            }
396           
397            /**
398             * Adds all nodes in an iterable to the list.
399             */
400//          public void addAll(Iterable<? extends T> list) {
401//              for (T e : list)
402//                  add(e);
403//          }
404           
405            /**
406             * Adds all nodes in an array to the list.
407             */
408             public <S extends T> void addAll(S[] list) {
409                 for (S e : list)
410                     add(e);
411            }
412           
413    }
414
415   
416    /**
417     * Replace <code>from</code> with <code>to</code>.
418     *
419     * Search through children after <code>from</code>. If it is found,
420     * replace it with <code>to</code> and return <code>true</code>.
421     * Comparisons are done with ==, not with equals().
422     */
423    public boolean List.replaceChild(T oldNode, T newNode) {
424        int n = getNumChildNoTransform();
425        for (int i = 0; i < n; i++) {
426            if (getChildNoTransform(i) == oldNode) {
427                setChild(newNode, i);
428                return true;
429            }
430        }
431        return false;
432    }
433   
434    /**
435     * Return a copy of node that is not in any tree.
436     *
437     * Returns <code>this</code> if node has no parent, <code>fullCopy()</code> otherwise.
438     */
439    public ASTNode ASTNode.unboundCopy() {
440        return (parent == null) ? this : fullCopy();
441    }
442   
443    /**
444     * Check if this node is a direct child (only List/Opt between) of <code>parent</code>.
445     */
446    public boolean ASTNode.isChildOf(BaseNode parent) {
447        ASTNode par = getParent();
448        return par != null && par.isChildOfHelper(parent);
449    }
450   
451    /**
452     * Helper method for {@link #isChildOf(BaseNode parent)}, should not be called directly.
453     */
454    protected boolean ASTNode.isChildOfHelper(BaseNode parent) {
455        return isChildOf(parent);
456    }
457
458    protected boolean BaseNode.isChildOfHelper(BaseNode parent) {
459        return parent == this;
460    }
461
462    /**
463     * Returns an iterable, that has an iterator that iterates over all direct FExp children.
464     *
465     * The iterator passes through Lists and Opts.
466     */
467    public Iterable<FExp> FExp.childFExps() {
468        return new ChildTypedIterable(FExp.class);
469    }
470
471    /**
472     * Returns an iterable, that has an iterator that iterates over all direct SrcExp children.
473     *
474     * The iterator passes through Lists and Opts.
475     */
476    public Iterable<SrcExp> SrcExp.childSrcExps() {
477        return new ChildTypedIterable(SrcExp.class);
478    }
479    public Iterable<SrcExp> SrcArrayConstructor.childSrcExps() {
480        return getSrcFunctionArguments().childSrcExps();
481    }
482
483    /**
484     * Returns an iterable, that has an iterator that iterates over the SrcExps
485     * that comprise this set of arguments.
486     *
487     * Note that this is different from the function with the same name on SrcExp.
488     */
489    public Iterable<SrcExp> SrcFunctionArguments.childSrcExps() {
490        Iterable<SrcExp> namedPart = 
491                new TransformerIterable<SrcNamedArgument, SrcExp>(getSrcNamedArguments())
492            {
493                protected SrcExp transform(SrcNamedArgument a) {
494                    return a.getSrcExp();
495                }
496            };
497        return new ChainedIterable(getSrcExps(), namedPart);
498    }
499
500    public class ASTNode {
501       
502        protected class ChildTypedIterable<S extends ASTNode<?>> implements Iterable<S> {
503            private Class<S> type;
504           
505            public ChildTypedIterable(Class<S> type) {
506                this.type = type;
507            }
508           
509            public Iterator<S> iterator() {
510                return new ChildTypedIterator(type);
511            }
512        }
513       
514       
515        private class ChildTypedIterator<S extends ASTNode<?>> implements Iterator<S> {
516           
517            private Iterator<T> it1;
518            private Iterator<ASTNode> it2;
519            private S next = null;
520            private Class<S> type;
521           
522            public ChildTypedIterator(Class<S> type) {
523                this.type = type;
524                it1 = iterator();
525                it2 = null;
526                update();
527            }
528           
529            private void update() {
530                boolean cont = true;
531                ASTNode node = null;
532                while (cont) {
533                    node = null;
534                    if (it2 == null) {
535                        if (it1.hasNext())
536                            node = it1.next();
537                        else 
538                            cont = false;
539                        if (node instanceof List || node instanceof Opt)
540                            it2 = node.iterator();
541                    } else {
542                        if (it2.hasNext()) 
543                            node = it2.next();
544                        else 
545                            it2 = null;
546                    }
547                    if (type.isInstance(node)) 
548                        cont = false;
549                }
550                next = (S) node;
551            }
552
553            public boolean hasNext() {
554                return next != null;
555            }
556
557            public S next() {
558                S res = next;
559                update();
560                return res;
561            }
562
563            public void remove() {
564                throw new UnsupportedOperationException();
565            }
566           
567        }
568       
569    }
570
571}
572
573/**
574 * Utility methods.
575 */
576aspect Utility {
577
578    /**
579     * Utility methods available from every class.
580     */
581    public class ASTNode {
582        /**
583         * Returns the intersection of two sets.
584         *
585         * @param a
586         *          A set.
587         * @param b
588         *          A set.
589         * @return
590         *          A set containing elements that exist in both {@code a} and {@code b}.
591         */
592        public static <T> Set<T> intersection(Set<T> a, Set<T> b) {
593            // TODO: use runtime type of a instead - problematic if it is something like HashMap.KeySet.
594            Set<T> res = new HashSet<T>();
595            res.addAll(a);
596            res.retainAll(b);
597            return res;
598        }
599
600        /**
601         * Short-hand method for sorting a collection.
602         *
603         * @param elems
604         *          The elements to sort.
605         * @param cmp
606         *          The {@link Comparator} to use when calculating the ordering of {@code elems}.
607         */
608        public static <T> ArrayList<T> toSortedList(Collection<T> elems, Comparator<? super T> cmp) {
609            ArrayList<T> res = new ArrayList<T>(elems.size());
610            res.addAll(elems);
611            Collections.sort(res, cmp);
612            return res;
613        }
614
615    }
616
617}
618
619aspect FileNames {
620   
621    protected Object BaseNode.fName = null;
622   
623    public class SourceLocation{
624        private String fName;
625        private int start;
626        private int end;
627        public SourceLocation(String fName, int start, int end){
628                setLocation(fName, start, end);
629        }
630        public String getFile(){ return fName; }
631        public int getStart(){ return start; }
632        public int getEnd(){ return end; }
633        public void setLocation(String fName, int start, int end){
634                this.fName = fName;
635                this.start = start;
636                this.end = end; 
637        }
638        public int getStartLine(){ return Symbol.getLine(start); }
639        public int getStartColumn(){ return Symbol.getColumn(start); }
640        public int getEndLine(){ return Symbol.getLine(end); }
641        public int getEndColumn(){ return Symbol.getColumn(end); }
642    }
643   
644   
645    public Object BaseNode.fileNames() {
646        if (fName == null)
647            fName = retrieveFileName();
648                return fName;
649    }
650    public Object ASTNode.fileNames() {
651        return fileName();
652    }
653   
654
655    public String ASTNode.fileName() { 
656        return retrieveFileName(); 
657    }
658    public String BaseNode.fileName() {
659        if (fName == null){
660            fName = retrieveFileName();
661        }
662        if(fName instanceof SourceLocation[]){
663                return ((SourceLocation[])this.fName)[0].getFile();
664        }
665                return (String)fName;
666    }
667    public String Root.fileName() {
668        if(fName instanceof SourceLocation[]){
669                        return ((SourceLocation[])fName)[0].getFile();
670                }
671                return (String)fName;
672       
673    }
674    public String SrcLibNode.fileName() {
675        return getStructured() ? myPackageFile().toString() : getLoadInfo().getPath();
676    }
677    public String InstLibNode.fileName() {
678        return actualInstClass().fileName();
679    }
680   
681    syn String ASTNode.dirName() = 
682        fileName().replaceFirst("^[^\\\\/]*$", ".").replaceFirst("[\\\\/][^\\\\/]*$", "");
683    eq SrcLibNode.dirName() = getStructured() ? getLoadInfo().getPath() : super.dirName();
684
685    inh String ASTNode.retrieveFileName();
686    eq BaseNode.getChild().retrieveFileName()         = fileName();
687    eq SrcLibNode.getChild().retrieveFileName()       = fileName();
688    eq InstLibNode.getChild().retrieveFileName()      = getSrcClassDecl().fileName();
689    eq Program.getAnonymousClass().retrieveFileName() = ParserHandler.ANONYMOUS_CLASS_FILENAME.getPath();
690   
691    public void Root.setFileName(String fName)             { this.fName = fName; }
692    public void SrcStoredDefinition.setFileName(String fName) { this.fName = fName; }
693}
694   
695aspect Names {
696  // simple names
697  syn String SrcIdDecl.name()            = getID();
698  syn String SrcAccess.name();
699  eq SrcNamedAccess.name()               = getID();
700  syn lazy String SrcGlobalAccess.name() = "." + getSrcAccessNoTransform().name();
701  syn lazy String SrcDot.name() {
702          StringBuilder buf = new StringBuilder();
703          List<SrcNamedAccess> l = getSrcNamedAccessListNoTransform();
704          for (int i = 0; i < l.getNumChildNoTransform(); i++) {
705                  buf.append(l.getChildNoTransform(i).name());
706                  buf.append('.');
707          }
708          return buf.substring(0, buf.length() - 1);
709  }
710 
711   // simple names of InstAccess:es
712  syn String InstAccess.name();
713  eq InstNamedAccess.name()               = getID();
714  syn lazy String InstGlobalAccess.name() = "." + getInstAccessNoTransform().name();
715  syn lazy String InstDot.name() {
716          StringBuilder buf = new StringBuilder();
717          List<InstAccess> l = getInstAccessListNoTransform();
718          for (int i = 0; i < l.getNumChildNoTransform(); i++) {
719                  buf.append(l.getChildNoTransform(i).name());
720                  buf.append('.');
721          }
722          return buf.substring(0, buf.length() - 1);
723  }
724 
725  syn String InstNamedModification.name() = getNameNoTransform().name();
726
727    syn String SrcAccess.qualifiedName();
728    eq SrcNamedAccess.qualifiedName()   = getID();
729    eq SrcGlobalAccess.qualifiedName()  = "." + getSrcAccess().qualifiedName();
730    eq SrcDot.qualifiedName() {
731        StringBuilder buf = new StringBuilder();
732        for (SrcNamedAccess a : getSrcNamedAccesss()) {
733            buf.append(a.qualifiedName());
734            buf.append('.');
735        }
736        return buf.substring(0, buf.length() - 1);
737    }
738
739  syn String InstAccess.qualifiedName();
740  eq InstNamedAccess.qualifiedName()           = getID();
741  eq InstDot.qualifiedName() {
742          StringBuilder buf = new StringBuilder();
743          for (InstAccess ia : getInstAccesss()) {
744                  buf.append(ia.qualifiedName());
745                  buf.append('.');
746          }
747          return buf.substring(0, buf.length() - 1);
748  }
749  eq InstGlobalAccess.qualifiedName()         = "." + getInstAccess().qualifiedName();
750
751    syn String SrcElement.name()       = null;
752    syn String SrcComponentDecl.name() = getNameNoTransform().getID();
753    eq SrcClassDecl.name()             = getNameNoTransform().getID();
754    eq SrcExtendsClause.name()         = getSuperNoTransform().name();
755
756  syn String SrcFunctionCall.name() = getNameNoTransform().name();
757 
758  syn String InstImport.name();
759  eq InstImportQualified.name()   = getPackageNameNoTransform().lastName();
760  eq InstImportRename.name()      = 
761          ((SrcImportClauseRename) getSrcImportClause()).getSrcIdDeclNoTransform().getID();
762  eq InstImportUnqualified.name() = "*";    // To avoid returning null
763 
764  syn String SrcAccess.lastName() = name();
765  eq SrcDot.lastName()            = getSrcNamedAccessListNoTransform().lastChildNoTransform().lastName();
766  eq SrcGlobalAccess.lastName()   = getSrcAccessNoTransform().lastName();
767 
768  syn String InstAccess.lastName() = name();
769  eq InstDot.lastName()            = getInstAccessListNoTransform().lastChildNoTransform().lastName();
770  eq InstGlobalAccess.lastName()   = getInstAccessNoTransform().lastName();
771 
772  public T List.lastChildNoTransform() {
773          return getChildNoTransform(getNumChildNoTransform() - 1);
774  }
775
776    syn String SrcClassDecl.qualifiedName() = combineName(classNamePrefix(), name());
777    syn String SrcComponentDecl.qualifiedName() = combineName(classNamePrefix(), name());
778    inh String SrcClassDecl.classNamePrefix();
779    inh String SrcComponentDecl.classNamePrefix();
780    eq SrcFullClassDecl.getChild().classNamePrefix() = combineName(classNamePrefix(), name());
781    eq SrcBuiltInClassDecl.qualifiedName() = getName().getID();
782
783    // For proxy
784    public String SourceRoot.computeClassNamePrefix() {
785        return "";
786    }
787
788    eq SourceRoot.getProgram().classNamePrefix() = computeClassNamePrefix();
789    eq Root.getChild().classNamePrefix() = "";
790
791    /**
792     * Compose a dotted name of two components.
793     *
794     * Each component can be a dotted name, a single name or empty.
795     */
796    public static String ASTNode.combineName(String first, String second) {
797        if (first.isEmpty())
798            return second;
799        if (second.isEmpty())
800            return first;
801        return first + "." + second;
802    }
803
804    syn String InstClassDecl.primitiveName() = name();
805    eq InstLibNode.primitiveName()           = resolveLib().name();
806
807    eq InstFullClassDecl.primitiveName() {
808        if (extendsPrimitive())
809            return getInstExtends(0).myInstClass().finalClass().primitiveName();
810        else 
811            return name();
812    }
813
814    syn String InstForIndex.name() = getInstPrimitiveNoTransform().name();
815    syn String FForIndex.name()    = getFVariableNoTransform().name();
816
817    syn String InstAccess.enclosingName() = "";
818    eq InstDot.enclosingName()           = name().substring(0, name().lastIndexOf('.'));
819    eq InstGlobalAccess.enclosingName()  = name().substring(0, name().lastIndexOf('.'));
820
821    eq InstComponentDecl.getInstModification().calcInstanceName() = buildInstanceName(surroundingInstClass(), getFAccessPrefix());
822    eq InstComponentDecl.getChild().calcInstanceName()            = buildInstanceName(surroundingInstClass(), getFAccess());
823    eq InstClassDecl.getChild().calcInstanceName()                = buildInstanceName(this, new FAccessEmpty());
824    eq InstProgramRoot.getChild().calcInstanceName() {
825        throw new UnsupportedOperationException("Missing equation for inh calcInstanceName().");
826    }
827
828    /**
829     * Create an instance name from a class declaration and a suffix.
830     */
831    syn String InstNode.buildInstanceName(InstClassDecl cls, FAccess suffix) =
832        (suffix.numParts() == 0) ? cls.name() : cls.name() + '.' + suffix.name();
833
834  inh String InstExternal.packageName();
835  inh String InstBaseClassDecl.packageName();
836  eq InstBaseClassDecl.getChild().packageName() = isPackage() ? qualifiedName() : packageName();
837  eq Root.getChild().packageName() = null;
838 
839  syn String InstExternal.libraryName() = findLibraryName();
840  syn String InstNode.libraryName() {
841          InstClassDecl icd = myInstClass();
842          String res = icd.isUnknown() ? findLibraryName() : icd.findLibraryName();
843          return (res == null) ? name() : res;
844  }
845 
846  inh String InstExternal.findLibraryName();
847  inh String InstNode.findLibraryName();
848  eq InstNode.getChild().findLibraryName() = libraryName();
849  eq InstRoot.getChild().findLibraryName() = null;
850  eq Root.getChild().findLibraryName()     = null;
851
852    inh String ASTNode.packagePath(String name);
853    eq Root.getChild().packagePath(String name) = null;
854    eq InstNode.getChild().packagePath(String name) {
855        InstLookupResult<InstClassDecl> icd = lookupInstClassQualifiedGlobal(name);
856        return icd.successful() ? icd.target().dirName() : null;
857    }
858    eq SrcFullClassDecl.getChild().packagePath(String name) {
859        SrcClassDecl cd = simpleLookupClass(new QualifiedName(name, true));
860        return (cd == null || cd.isUnknown()) ? null : cd.dirName();
861    }
862
863  inh String ASTNode.topPackagePath();
864  eq Root.getChild().topPackagePath() = null;
865  eq InstClassDecl.getChild().topPackagePath() {
866      String path = topPackagePath();
867          return (path == null) ? dirName() : path;
868  }
869  eq SrcFullClassDecl.getChild().topPackagePath() {
870          String path = topPackagePath();
871          return (path == null) ? dirName() : path;
872  }
873
874    ASTNode implements URIResolver.PackageNode;
875
876    public String ASTNode.resolveURI(String str) throws URIException {
877        return URIResolver.DEFAULT.resolveURIChecked(this, str);
878    }
879
880        syn boolean InstNode.isLibNode() = false;
881    eq InstLibNode.isLibNode()       = true; 
882
883        /**
884         * Any closest ancestor instClass but not stopping at InstComponents and returning it's class
885         * as opposed to enclosingInstClassDecl().
886         */ 
887    inh InstClassDecl InstNode.containingInstClass();
888    eq InstClassDecl.getChild().containingInstClass() = this;
889    eq InstRoot.getChild().containingInstClass()      = unknownInstClassDecl();
890
891    inh InstNode InstNode.enclosingInstNode();
892    eq InstNode.getChild().enclosingInstNode() = this;
893   
894    inh InstClassDecl ASTNode.enclosingInstClassDecl();
895    eq SourceRoot.getProgram().enclosingInstClassDecl()      = null;
896    eq FlatRoot.getChild().enclosingInstClassDecl()          = null;
897    eq InstBaseClassDecl.getChild().enclosingInstClassDecl() = this;
898    eq InstComponentDecl.getChild().enclosingInstClassDecl() = myInstClass();
899
900    /**
901     * Any closest ancestor InstanceComponent which is a parent to this one.
902     * This method doesn't stop at classes which enclosingInstComponent does.
903     */
904
905    inh InstComponentDecl InstComponentDecl.parentInstComponent();
906    eq InstRoot.getChild().parentInstComponent()          = null;
907    eq InstComponentDecl.getChild().parentInstComponent() = this;
908
909    /**
910     * The closest ancestor instComponentDecl if there is one before the closest class.
911     * This method stops at classes.
912     */
913    inh InstComponentDecl InstComponentDecl.enclosingInstComponentDecl();
914    inh InstComponentDecl InstExtends.enclosingInstComponentDecl();
915    eq BaseNode.getChild().enclosingInstComponentDecl()          = null;
916    eq InstExtends.getChild().enclosingInstComponentDecl()       = enclosingInstComponentDecl();
917    eq InstComponentDecl.getChild().enclosingInstComponentDecl() = this;
918
919    inh SrcBaseClassDecl ASTNode.enclosingClassDecl();
920    eq Root.getChild().enclosingClassDecl() = null;
921
922    eq SrcFullClassDecl.getSrcClause().enclosingClassDecl()         = this;
923    eq SrcFullClassDecl.getSrcAnnotation().enclosingClassDecl()     = this; 
924    eq SrcFullClassDecl.getSrcExternalClause().enclosingClassDecl() = this;
925
926    eq SrcShortClassDecl.getSrcExtendsClauseShortClass().enclosingClassDecl() = this;
927   
928    inh Set<SrcClassDecl> SrcClassDecl.enclosingClassDecls();
929    inh Set<SrcClassDecl> SrcComponentDecl.enclosingClassDecls();
930    eq Root.getChild().enclosingClassDecls() = Collections.emptySet();
931    eq SrcClassDecl.getChild().enclosingClassDecls() {
932        Set<SrcClassDecl> enclosingClassDecls = new HashSet<>(enclosingClassDecls());
933        enclosingClassDecls.add(this);
934        return enclosingClassDecls;
935    }
936
937    inh FStatement FStatement.enclosingLoop();
938    eq FAlgorithm.getChild().enclosingLoop()     = null;
939    eq Root.getChild().enclosingLoop()           = null;
940    eq FWhileStmt.getWhileStmt().enclosingLoop() = this;
941    eq FForStmt.getForStmt().enclosingLoop()     = this;
942    eq InstForStmt.getForStmt().enclosingLoop()  = this;
943
944
945    /**
946     * Access method for the last SrcAccess of a qualified or
947     * unqualified name.
948     */ 
949    syn SrcAccess SrcAccess.getLastAccess() = this;
950    eq SrcDot.getLastAccess()            = getSrcNamedAccess(getNumSrcNamedAccess() - 1);
951    eq SrcGlobalAccess.getLastAccess()   = getSrcAccess().getLastAccess();
952   
953    syn InstAccess InstAccess.getLastInstAccess() = this;
954    eq InstDot.getLastInstAccess()                = getInstAccess(getNumInstAccessNoTransform() - 1);
955    eq InstGlobalAccess.getLastInstAccess()       = getInstAccess().getLastInstAccess();
956   
957    /**
958     * Access method for the first SrcAccess of a qualified or
959     * unqualified name.
960     */
961    syn SrcAccess SrcAccess.getFirstAccess() = this;
962    eq SrcDot.getFirstAccess()            = getSrcNamedAccess(0);
963    eq SrcGlobalAccess.getFirstAccess()   = getSrcAccess().getFirstAccess();
964
965    // For proxy
966    public SrcAccess SourceRoot.computeNextAccess() {
967        return null;
968    }
969   
970    inh SrcAccess SrcAccess.getNextAccess();
971    eq SrcDot.getSrcNamedAccess(int i).getNextAccess()    = (i >= getNumSrcNamedAccess() - 1) ? null : getSrcNamedAccess(i + 1);
972    eq SourceRoot.getProgram().getNextAccess() = computeNextAccess();
973    eq Root.getChild().getNextAccess()         = null;
974
975    /**
976     * SrcAccess method for the first SrcAccess of a qualified or
977     * unqualified name.
978     */
979    syn InstAccess InstAccess.getFirstInstAccess() = this;
980    eq InstDot.getFirstInstAccess()                = getInstAccess(0);
981    eq InstGlobalAccess.getFirstInstAccess()       = getInstAccess().getFirstInstAccess();
982   
983    inh InstAccess InstAccess.getNextInstAccess();
984    eq InstDot.getInstAccess(int i).getNextInstAccess() = 
985                (i >= getNumInstAccessNoTransform() - 1) ? null : getInstAccess(i + 1);
986    eq BaseNode.getChild().getNextInstAccess()          = null;
987   
988    /**
989     * Iterable of all parts of this access
990     */
991    syn Iterable<InstAccess> InstAccess.allParts() = Arrays.asList(this);
992    eq InstDot.allParts() = getInstAccessList();
993   
994    /**
995     * Find the parent access for this subscript
996     */
997    inh InstAccess FSubscript.myInstAccess();
998    eq Root.getChild().myInstAccess() = null;
999    eq InstNode.getChild().myInstAccess() = null;
1000    eq InstAccess.getChild().myInstAccess() = this;
1001   
1002    /**
1003     * stripFirstAccess removes the first access in a qualified
1004     * name. If the name is not qualified, null is returned.
1005     */
1006    public SrcAccess SrcAccess.stripFirstAccess() {
1007        return null;
1008    }
1009   
1010    public SrcAccess SrcDot.stripFirstAccess() {
1011        int n = getNumSrcNamedAccess();
1012        if (n <= 2)
1013                return getSrcNamedAccess(n - 1);
1014        List<SrcNamedAccess> l = new List<>();
1015        for (int i = 1; i < n; i++)
1016                l.add(getSrcNamedAccess(i));
1017        return new SrcDot(l);
1018    }
1019   
1020    public SrcAccess SrcGlobalAccess.stripFirstAccess() {
1021        return getSrcAccess().stripFirstAccess();
1022    }
1023   
1024    syn boolean SrcAccess.isQualified() = false;
1025    eq SrcDot.isQualified()             = true;
1026    eq SrcGlobalAccess.isQualified()    = getSrcAccess().isQualified();
1027   
1028    /**
1029     * Get the top node in an access (possibly qualified).
1030     */
1031    syn SrcAccess SrcAccess.getTopAccess() = retrieveTopAccess(this);
1032   
1033    inh SrcAccess SrcAccess.retrieveTopAccess(SrcAccess pre);
1034    eq ASTNode.getChild().retrieveTopAccess(SrcAccess pre)      = pre;
1035    eq SrcDot.getChild().retrieveTopAccess(SrcAccess pre)          = retrieveTopAccess(this);
1036    eq SrcGlobalAccess.getChild().retrieveTopAccess(SrcAccess pre) = retrieveTopAccess(this);
1037   
1038    syn boolean SrcAccess.isGlobal() = false;
1039    eq SrcGlobalAccess.isGlobal()    = true;
1040   
1041    syn boolean InstAccess.isTopInstAccess() = this == getTopInstAccess();
1042   
1043    /**
1044     * Get the top node in an access (possibly qualified).
1045     */
1046    syn InstAccess InstAccess.getTopInstAccess() = retrieveTopInstAccess(this);
1047   
1048    inh InstAccess InstAccess.retrieveTopInstAccess(InstAccess pre);
1049    eq BaseNode.getChild().retrieveTopInstAccess(InstAccess pre)         = pre;
1050    eq InstDot.getChild().retrieveTopInstAccess(InstAccess pre)          = retrieveTopInstAccess(this);
1051    eq InstGlobalAccess.getChild().retrieveTopInstAccess(InstAccess pre) = this;
1052
1053    /**
1054     * Check if this access is a name part of a qualified access.
1055     */
1056    inh boolean SrcAccess.inQualified();
1057    inh boolean InstAccess.inQualified();
1058    eq SrcDot.getSrcNamedAccess().inQualified()         = true;
1059    eq InstDot.getInstAccess().inQualified() = true;
1060    eq BaseNode.getChild().inQualified()     = false;
1061
1062    /**
1063     * Get the array subscripts of the last name part.
1064     */
1065    syn FArraySubscripts InstAccess.getLastFArraySubscripts() = 
1066        getLastInstAccess().getFArraySubscripts();
1067   
1068    syn FArraySubscripts InstAccess.getFArraySubscripts() = null;
1069    eq InstDot.getFArraySubscripts() = getLastInstAccess().getFArraySubscripts();
1070
1071    syn boolean InstAccess.hasFArraySubscripts() = false;
1072    eq InstArrayAccess.hasFArraySubscripts() = true;
1073    eq InstDot.hasFArraySubscripts() = getLastInstAccess().hasFArraySubscripts();
1074
1075    /**
1076     * Is this an access to a component?
1077     */
1078    syn boolean InstAccess.isComponentAccess() = false;
1079    eq InstComponentAccess.isComponentAccess() = true;
1080
1081    /**
1082     * Is this an access to a class?
1083     */
1084    syn boolean InstAccess.isClassAccess() = false;
1085    eq InstClassAccess.isClassAccess()     = true;
1086
1087    /**
1088     * Copy this access, append a name part to the copy and return the copy.
1089     */
1090    public InstDot InstAccess.copyAndAppend(String id) {
1091        InstAccess left = fullCopy();
1092        InstAccess right = createPartToAppend(id);
1093        return new InstDot(new List<InstAccess>().add(left).add(right));
1094    }
1095   
1096    public InstDot InstDot.copyAndAppend(String id) {
1097        InstDot res = fullCopy();
1098        res.addInstAccess(createPartToAppend(id));
1099        return res;
1100    }
1101   
1102    /**
1103     * Create an InstAccess suitable for appending to this access.
1104     */
1105    public InstAccess InstAccess.createPartToAppend(String id) {
1106        return new InstParseAccess(id);
1107    }
1108   
1109    public InstAccess InstComponentAccess.createPartToAppend(String id) {
1110        return new InstComponentAccess(id);
1111    }
1112   
1113}
1114
1115aspect Slices {
1116   
1117    /**
1118     * Check if this is a slice operation.
1119     */
1120    syn boolean FExp.isSlice() = true;
1121    eq CommonAccessExp.isSlice() = isArray() && getAccess().isSlice();
1122    eq FSubscriptedExp.isSlice() = isArray();
1123   
1124    syn boolean CommonAccess.isSlice();
1125    eq InstAccess.isSlice() {
1126        java.util.List<FArraySubscripts> l = allFArraySubscripts();
1127        int last = l.size() - 1;
1128        for (int i = 0; i < last; i++) {
1129            if (l.get(i).accessNdims() > 0) {
1130                return true;
1131            }
1132        }
1133        return l.get(last).isSlice();
1134    }
1135   
1136    syn boolean FArraySubscripts.isSlice() = ndims() > 0;
1137    eq FArrayExpSubscripts.isSlice() {
1138        for (FSubscript fs : getFSubscripts()) {
1139            if (fs.isSlice()) {
1140                return true;
1141            }
1142        }
1143        return false;
1144    }
1145   
1146    syn boolean FSubscript.isSlice() = true;
1147    eq FColonSubscript.isSlice()     = false;
1148    eq FExpSubscript.isSlice()       = getFExp().isSliceFAS(mySize());
1149   
1150    syn boolean FExp.isSliceFAS(Size size) = true;
1151    eq FRangeExp.isSliceFAS(Size size) =
1152         !getFExp(0).isLiteral(1) ||
1153         (getNumFExp() > 2 && !getFExp(1).isLiteral(1)) ||
1154         size.isSliceFAS(getFExp(getNumFExp()-1));
1155   
1156    public boolean Size.isSliceFAS(FExp exp) {
1157        return isUnknown() || !exp.isLiteral(get(0));
1158    }
1159   
1160    syn boolean FExp.isLiteral(int i)  = false;
1161    eq FIntegerLitExp.isLiteral(int i) = getValue() == i;
1162   
1163    /**
1164     * Check if this is a slice operation.
1165     */
1166    eq FAccess.isSlice() = false;
1167    eq FAccessFull.isSlice() {
1168        int n = getNumFAccessPart() - 1;
1169        for (int i = 0; i < n; i++) {
1170                FAccessPart part = getFAccessPart(i);
1171                if (part.hasFArraySubscripts())
1172                        for (Subscript s : part.getFArraySubscripts().subscripts())
1173                                if (s.ndims() > 0)
1174                                        return true;
1175        }
1176                FAccessPart part = getFAccessPart(n);
1177        return part.hasFArraySubscripts() && part.getFArraySubscripts().isSlice();
1178    }
1179}
1180
1181
1182aspect DebugHelpers {
1183   
1184    /**
1185     * Convert to string. Primarily useful for debugging.
1186     *
1187     * Default implementation uses prettyPrint().
1188     */
1189    public String ASTNode.toString() {
1190        return prettyPrint("");
1191    }
1192
1193    /**
1194     * Override simple expressions for performance reasons
1195     */
1196
1197    public String FRealLitExp.toString()         { return Double.toString(getValue()); }
1198    public String FIntegerLitExp.toString()      { return Integer.toString(getValue()); }
1199    public String FBooleanLitExpTrue.toString()  { return "true"; }
1200    public String FBooleanLitExpFalse.toString() { return "false"; }
1201    public String FStringLitExp.toString()       { return "\"" + getString() + "\""; }
1202    public String FEnumLitExp.toString()         { return getEnum() + "." + getValue(); }
1203
1204    public String FAccessString.toString()        { return getName(); }
1205
1206}
1207
1208
1209aspect Visibility {
1210
1211    inh boolean SrcElement.isPublic();
1212    inh boolean SrcComponentDecl.isPublic();
1213    inh boolean SrcExtendsClause.isPublic();
1214    eq SrcPublicElementList.getSrcElement().isPublic()    = true;
1215    eq SrcProtectedElementList.getSrcElement().isPublic() = false;
1216    eq SourceRoot.getProgram().isPublic()           = true; 
1217    eq Root.getChild().isPublic()                   = true; 
1218
1219    syn boolean InstNode.isPublic();
1220    eq InstRoot.isPublic()          = true;
1221    eq InstClassDecl.isPublic()     = getSrcClassDecl().isPublic();
1222    eq InstComponentDecl.isPublic() = getSrcComponentDecl().isPublic();
1223    eq InstExtends.isPublic()       = getSrcExtendsClause().isPublic();
1224
1225    syn boolean SrcElement.isProtected()        = !isPublic();
1226    syn boolean SrcComponentDecl.isProtected()  = !isPublic();
1227    syn boolean InstClassDecl.isProtected()     = getSrcClassDecl().isProtected();
1228    syn boolean InstComponentDecl.isProtected() = getSrcComponentDecl().isProtected();
1229
1230    inh boolean InstNode.inProtectedComponent();
1231    eq InstComponentDecl.getChild().inProtectedComponent()     = isProtected() || inProtectedComponent();
1232    eq InstClassDecl.getChild().inProtectedComponent()         = false;
1233    eq Root.getChild().inProtectedComponent()                  = false;
1234    eq InstRecordConstructor.getChild().inProtectedComponent() = false;
1235
1236    syn boolean InstAssignable.isPublicVar() = isPublic() && !inProtectedComponent();
1237
1238
1239    syn boolean FVariable.isPublic()    = getVisibilityType().isPublic();
1240    syn boolean FVariable.isProtected() = getVisibilityType().isProtected();
1241
1242    syn boolean FAbstractVariable.isTemporary() = false;
1243    eq FVariable.isTemporary()                  = getVisibilityType().isTemporary();
1244
1245    syn boolean FAbstractVariable.isInterface() = false;
1246    eq FVariable.isInterface()                  = getVisibilityType().isInterface();
1247
1248    syn boolean FAbstractVariable.isFromExpandableConnector() = false;
1249    eq FVariable.isFromExpandableConnector()                  = 
1250        getVisibilityType().isFromExpandableConnector();
1251
1252}
1253
1254
1255aspect ComponentDeclMethods {
1256
1257    inh boolean InstComponentDecl.isConnectorVariable();
1258    eq InstClassDecl.getChild().isConnectorVariable() = isConnector();
1259    eq InstComponentDecl.getChild().isConnectorVariable() = isConnector() || isConnectorVariable();
1260    eq InstRoot.getChild().isConnectorVariable() = false;
1261
1262    /**
1263     * Check if a SrcComponentDecl is declared flow.
1264     */
1265    syn boolean SrcComponentDecl.isFlow()  = hasSrcTypePrefixFlow() && getSrcTypePrefixFlow().isFlow();
1266    syn boolean SrcTypePrefixFlow.isFlow() = false;
1267    eq SrcFlow.isFlow()                    = true;
1268
1269    /**
1270     * Check if a SrcComponentDecl is declared stream.
1271     */
1272    syn boolean SrcComponentDecl.isStream()  = hasSrcTypePrefixFlow() && getSrcTypePrefixFlow().isStream();
1273    syn boolean SrcTypePrefixFlow.isStream() = false;
1274    eq SrcStream.isStream()                  = true;
1275
1276    /**
1277     * Check if a SrcComponentDecl is declared flow or stream.
1278     */
1279    syn boolean SrcComponentDecl.hasFlowOrStream() = hasSrcTypePrefixFlow();
1280
1281    /**
1282     * Check if a SrcComponentDecl is declared inner.
1283     */
1284    syn boolean SrcComponentDecl.isInner() = hasInner();
1285
1286    /**
1287     * Check if a SrcComponentDecl is declared outer.
1288     */
1289    syn boolean SrcComponentDecl.isOuter() = hasOuter();
1290
1291    /**
1292     * Check if a SrcComponentDecl is declared inner or outer.
1293     */
1294    syn boolean SrcComponentDecl.hasInnerOrOuter() = hasInner() || hasOuter();
1295
1296    /**
1297     * Check if a SrcClassDecl is declared inner.
1298     */
1299    syn boolean SrcClassDecl.isInner() = false;
1300    eq SrcBaseClassDecl.isInner() = getInner();
1301
1302    /**
1303     * Check if a SrcClassDecl is declared outer.
1304     */
1305    syn boolean SrcClassDecl.isOuter() = false;
1306    eq SrcBaseClassDecl.isOuter() = getOuter();
1307
1308    /**
1309     * Check if a SrcClassDecl is declared inner or outer.
1310     */
1311    syn boolean SrcClassDecl.hasInnerOrOuter() = false;
1312    eq SrcBaseClassDecl.hasInnerOrOuter()      = getInner() || getOuter();
1313   
1314
1315    /**
1316     * Check if this component is declared parameter.
1317     */
1318    syn boolean SrcComponentDecl.isParameter() = hasSrcTypePrefixVariability() && getSrcTypePrefixVariability().parameterVariability();
1319   
1320    /**
1321     * Check if this component is declared constant.
1322     */
1323    syn boolean SrcComponentDecl.isConstant() = hasSrcTypePrefixVariability() && getSrcTypePrefixVariability().constantVariability();
1324   
1325    /**
1326     * Check if this component clause is declared constant.
1327     */
1328    syn boolean SrcComponentClause.isConstant() = hasSrcTypePrefixVariability() && getSrcTypePrefixVariability().constantVariability();
1329   
1330    /**
1331     * Check if this component is declared discrete.
1332     */
1333    syn boolean SrcComponentDecl.isDiscrete() = hasSrcTypePrefixVariability() && getSrcTypePrefixVariability().discreteVariability();
1334
1335    /**
1336     * Check if this component is an input component.
1337     */
1338    syn boolean InstComponentDecl.isInput() = isDeclaredInput() || inheritsInput();
1339   
1340    /**
1341     * Check if this component inherits input from the surrounding component.
1342     */
1343    syn boolean InstComponentDecl.inheritsInput() {
1344        InstComponentDecl source = inheritsInputOutputFrom();
1345        return source != null && source.isDeclaredInput();
1346    }
1347
1348    /**
1349     * Check if this component or its class is declared input.
1350     */
1351    syn boolean InstComponentDecl.isDeclaredInput() = 
1352        (isComponentDeclaredInput() || myInstClass().isInput()) && !inExpandableConnector();
1353
1354    /**
1355     * Check if this component is declared input.
1356     */
1357    syn boolean InstComponentDecl.isComponentDeclaredInput() = getSrcComponentDecl().isInput();
1358    eq InstReplacingComposite.isComponentDeclaredInput()     = 
1359        getSrcComponentDecl().hasSrcTypePrefixInputOutput() ? getSrcComponentDecl().isInput() : getOriginalInstComponent().isDeclaredInput();
1360    eq InstReplacingRecord.isComponentDeclaredInput()        = 
1361        getSrcComponentDecl().hasSrcTypePrefixInputOutput() ? getSrcComponentDecl().isInput() : getOriginalInstComponent().isDeclaredInput();
1362    eq InstReplacingPrimitive.isComponentDeclaredInput()     = 
1363        getSrcComponentDecl().hasSrcTypePrefixInputOutput() ? getSrcComponentDecl().isInput() : getOriginalInstComponent().isDeclaredInput();
1364
1365    /**
1366     * Check if this component is declared input.
1367     */
1368    syn boolean SrcComponentDecl.isInput() = hasSrcTypePrefixInputOutput() && getSrcTypePrefixInputOutput().isInput();
1369   
1370    /**
1371     * Check if this prefix is "input".
1372     */
1373    syn boolean SrcTypePrefixInputOutput.isInput() = false;
1374    eq SrcInput.isInput()                          = true;
1375
1376    /**
1377     * Check if this component is an output component.
1378     */
1379    syn boolean InstComponentDecl.isOutput() = 
1380        (isDeclaredOutput() || inheritsOutput()) && !inExpandableConnector();
1381   
1382    /**
1383     * Check if this component inherits output from the surrounding component.
1384     */
1385    syn boolean InstComponentDecl.inheritsOutput() {
1386        InstComponentDecl source = inheritsInputOutputFrom();
1387        return source != null && source.isDeclaredOutput();
1388    }
1389 
1390    /**
1391     * Check if this component is declared output.
1392     */
1393    syn boolean InstComponentDecl.isDeclaredOutput() = getSrcComponentDecl().isOutput() || myInstClass().isOutput();
1394
1395    /**
1396     * Check if this component is declared output.
1397     */
1398    syn boolean SrcComponentDecl.isOutput() = hasSrcTypePrefixInputOutput() && getSrcTypePrefixInputOutput().isOutput();
1399   
1400    /**
1401     * Check if this prefix is "output".
1402     */
1403    syn boolean SrcTypePrefixInputOutput.isOutput() = false;
1404    eq SrcOutput.isOutput()                         = true;
1405   
1406    /**
1407     * Find the component that this component inherits input or output from, if any.
1408     */
1409    inh InstComponentDecl InstComponentDecl.inheritsInputOutputFrom();
1410    eq InstComponentDecl.getChild().inheritsInputOutputFrom() {
1411        return (isDeclaredInput() || isDeclaredOutput()) ? this : inheritsInputOutputFrom();
1412    }
1413    eq InstPartialFunction.getChild().inheritsInputOutputFrom()    = null;
1414    eq InstArrayComponentDecl.getChild().inheritsInputOutputFrom() = inheritsInputOutputFrom();
1415    eq InstClassDecl.getChild().inheritsInputOutputFrom()     = null;
1416    eq InstRoot.getChild().inheritsInputOutputFrom()          = null;
1417    eq Root.getChild().inheritsInputOutputFrom()              = null;
1418   
1419    /**
1420     * Check if this component is part of a component that is declared input or output on the top level.
1421     */
1422    syn boolean InstComponentDecl.isTopLevelCausalOrConnector() = false;
1423    eq InstAssignable.isTopLevelCausalOrConnector() = isTopLevel() && !inExpandableConnector() && 
1424            (isInput() || isOutput() || isConnectorVariable()) && isPublicVar();
1425
1426    syn boolean InstComponentDecl.isTopLevel() = isInTopLevel();
1427
1428    inh boolean InstComponentDecl.isInTopLevel();
1429    eq InstComponentDecl.getChild().isInTopLevel() = (isAssignable() || isConnector()) && isTopLevel();
1430    eq InstClassDecl.getChild().isInTopLevel()     = true;
1431    eq Root.getChild().isInTopLevel()              = false;
1432
1433    /**
1434     * Check if this equation is declared initial.
1435     */
1436    inh boolean SrcAbstractEquation.isInitial();
1437    eq SrcEquationClause.getSrcAbstractEquation().isInitial()        = false;
1438    eq SrcInitialEquationClause.getSrcAbstractEquation().isInitial() = true;
1439
1440    /**
1441     * Check if this equation is declared initial.
1442     */
1443    syn boolean SrcAlgorithm.isInitial() = false;
1444    eq SrcInitialAlgorithm.isInitial()   = true;
1445
1446    /**
1447     * Check if this component is a flow component.
1448     */
1449    syn boolean InstComponentDecl.isFlow() = isDeclaredFlow() || inheritsFlow();
1450   
1451    /**
1452     * Check if this component inherits output from the surrounding component.
1453     */
1454    syn boolean InstComponentDecl.inheritsFlow() = inheritsFlowFrom() != null;
1455   
1456    /**
1457     * Find the component that this component inherits input or output from, if any.
1458     */
1459    inh InstComponentDecl InstComponentDecl.inheritsFlowFrom();
1460    eq InstComponentDecl.getChild().inheritsFlowFrom() = isDeclaredFlow() ? this : inheritsFlowFrom();
1461    eq InstClassDecl.getChild().inheritsFlowFrom()     = null;
1462    eq InstRoot.getChild().inheritsFlowFrom()          = null;
1463    eq Root.getChild().inheritsFlowFrom()              = null;
1464
1465    /**
1466     * Check if this component is declared flow.
1467     */
1468    syn boolean InstComponentDecl.isDeclaredFlow() = getSrcComponentDecl().isFlow();
1469    eq InstReplacingComposite.isDeclaredFlow()     = 
1470        getSrcComponentDecl().hasFlowOrStream() ? getSrcComponentDecl().isFlow() : getOriginalDecl().isFlow();
1471    eq InstReplacingRecord.isDeclaredFlow()        = 
1472        getSrcComponentDecl().hasFlowOrStream() ? getSrcComponentDecl().isFlow() : getOriginalDecl().isFlow();
1473    eq InstReplacingPrimitive.isDeclaredFlow()     = 
1474        getSrcComponentDecl().hasFlowOrStream() ? getSrcComponentDecl().isFlow() : getOriginalDecl().isFlow();
1475
1476    /**
1477     * Check if this component is declared stream.
1478     */
1479    syn boolean InstComponentDecl.isStream() = getSrcComponentDecl().isStream();
1480    eq InstReplacingComposite.isStream()     = 
1481        getSrcComponentDecl().hasFlowOrStream() ? getSrcComponentDecl().isStream() : getOriginalDecl().isStream();
1482    eq InstReplacingRecord.isStream()        = 
1483        getSrcComponentDecl().hasFlowOrStream() ? getSrcComponentDecl().isStream() : getOriginalDecl().isStream();
1484    eq InstReplacingPrimitive.isStream()     = 
1485        getSrcComponentDecl().hasFlowOrStream() ? getSrcComponentDecl().isStream() : getOriginalDecl().isStream();
1486
1487    /**
1488     * Check if this component is declared inner.
1489     */
1490    syn boolean InstComponentDecl.isInner() = getSrcComponentDecl().isInner() || isGeneratedInner();
1491    eq InstReplacingComposite.isInner()     = 
1492        getSrcComponentDecl().hasInnerOrOuter() ? getSrcComponentDecl().isInner() : getOriginalDecl().isInner();
1493    eq InstReplacingRecord.isInner()        = 
1494        getSrcComponentDecl().hasInnerOrOuter() ? getSrcComponentDecl().isInner() : getOriginalDecl().isInner();
1495    eq InstReplacingPrimitive.isInner()     = 
1496        getSrcComponentDecl().hasInnerOrOuter() ? getSrcComponentDecl().isInner() : getOriginalDecl().isInner();
1497
1498    /**
1499     * Check if this component is declared outer.
1500     */
1501    syn boolean InstComponentDecl.isOuter() = getSrcComponentDecl().isOuter() && !isGeneratedInner();
1502    eq InstReplacingComposite.isOuter()     = 
1503        getSrcComponentDecl().hasInnerOrOuter() ? getSrcComponentDecl().isOuter() : getOriginalDecl().isOuter();
1504    eq InstReplacingRecord.isOuter()        = 
1505        getSrcComponentDecl().hasInnerOrOuter() ? getSrcComponentDecl().isOuter() : getOriginalDecl().isOuter();
1506    eq InstReplacingPrimitive.isOuter()     = 
1507        getSrcComponentDecl().hasInnerOrOuter() ? getSrcComponentDecl().isOuter() : getOriginalDecl().isOuter();
1508
1509    /**
1510     * Check if this class is declared inner.
1511     */
1512    syn boolean InstClassDecl.isInner()            = getSrcClassDecl().isInner();
1513    eq InstReplacingFullClassDecl.isInner()        = 
1514        getSrcClassDecl().hasInnerOrOuter() ? getSrcClassDecl().isInner() : getOriginalClassDecl().isInner();
1515    eq InstReplacingShortClassDecl.isInner()       = 
1516        getSrcClassDecl().hasInnerOrOuter() ? getSrcClassDecl().isInner() : getOriginalClassDecl().isInner();
1517    eq InstReplacingSimpleShortClassDecl.isInner() = 
1518        getSrcClassDecl().hasInnerOrOuter() ? getSrcClassDecl().isInner() : getOriginalClassDecl().isInner();
1519
1520    /**
1521     * Check if this component is declared outer.
1522     */
1523    syn boolean InstClassDecl.isOuter() = getSrcClassDecl().isOuter();
1524    eq InstReplacingFullClassDecl.isOuter()        = 
1525        getSrcClassDecl().hasInnerOrOuter() ? getSrcClassDecl().isOuter() : getOriginalClassDecl().isOuter();
1526    eq InstReplacingShortClassDecl.isOuter()       = 
1527        getSrcClassDecl().hasInnerOrOuter() ? getSrcClassDecl().isOuter() : getOriginalClassDecl().isOuter();
1528    eq InstReplacingSimpleShortClassDecl.isOuter() = 
1529        getSrcClassDecl().hasInnerOrOuter() ? getSrcClassDecl().isOuter() : getOriginalClassDecl().isOuter();
1530
1531    /**
1532     * Check if this component is disabled by a conditional clause
1533     */
1534    syn boolean InstComponentDecl.isDisabled() {
1535        if (hasConditionalAttribute()) {
1536            try {
1537                CValue cval = getConditionalAttribute().ceval();
1538                return cval.hasBooleanValue() && !cval.booleanValue();
1539            } catch (ConstantEvaluationException e) {}
1540        }
1541        return false;
1542    }
1543   
1544    syn boolean InstAccess.isDisabled() = false;
1545    eq InstComponentAccess.isDisabled() = myInstComponentDecl().isDisabled();
1546    eq InstComponentArrayAccess.isDisabled() = myInstComponentDecl().isDisabled();
1547    eq InstDot.isDisabled() {
1548        for (InstAccess ia : getInstAccesss())
1549                if (ia.isDisabled())
1550                        return true;
1551        return false;
1552    }
1553
1554    /**
1555     * Check if this node is in a disabled condition component.
1556     *
1557     * Only valid in instance tree.
1558     */
1559    inh boolean ASTNode.inDisabledComponent();
1560    eq Root.getChild().inDisabledComponent()              = false;
1561    eq InstClassDecl.getChild().inDisabledComponent()     = false;
1562    eq InstComponentDecl.getChild().inDisabledComponent() = isDisabled() || inDisabledComponent();
1563
1564}
1565
1566aspect ClassDeclMethods {
1567    public boolean InstClassDecl.extendsClass(InstClassDecl icd) {
1568        if (equals(icd))
1569            return true;
1570        for (InstExtends ie : getInstExtendss()) {
1571            if (ie.myInstClass().extendsClass(icd))
1572                return true;
1573        }
1574        return false;
1575    }
1576
1577    /**
1578     * check if this node has a SrcLibNode as parent
1579     */
1580    inh boolean SrcClassDecl.isLib();
1581    eq SourceRoot.getChild().isLib() = false;
1582    eq SrcLibNode.getChild().isLib() = true;
1583    eq SrcFullClassDecl.getChild().isLib() = false;
1584
1585    syn boolean SrcBaseNode.isLibNode() = false;
1586    eq SrcLibNode.isLibNode()           = true;
1587    syn SrcLibNode SrcBaseNode.asSrcLibNode() {
1588        throw new UnsupportedOperationException();
1589    }
1590    syn SrcLibNode SrcLibNode.asSrcLibNode() = this;
1591}
1592
1593
1594aspect MultiDeclMethods {
1595   
1596    InstClassDecl implements InstCallable;
1597    InstPartialFunction  implements InstCallable;
1598    public interface InstCallable {
1599        public boolean isCallable();
1600        public boolean isCompleteFunction();
1601        public boolean canBeReplacedForMe(InstNode node);
1602        public void    collectErrors(ErrorCheckType checkType);
1603
1604        public boolean isRecord();
1605        public boolean isPrimitive();
1606        public boolean isExternalObject();
1607        public boolean isOperatorRecord();
1608        public boolean isUnknown();
1609       
1610        public InstClassDecl    asInstClassDecl();
1611        public InstNode         asInstNode();
1612        public InstCallable actualInstCallable();
1613        public InstClassDecl    actualInstClassDecl();
1614       
1615        public String qualifiedName();
1616        public String name();
1617       
1618        public ArrayList<InstComponentDecl> myCallInputs();
1619        public ArrayList<InstComponentDecl> myInputs();
1620        public ArrayList<InstComponentDecl> myOutputs();
1621        public ArrayList<InstComponentDecl> myNonInputs();
1622       
1623        public void flattenFunction(Flattener f);
1624    }
1625   
1626    syn InstClassDecl InstNode.asInstClassDecl() {
1627        throw new UnsupportedOperationException();
1628    }
1629    syn InstClassDecl InstClassDecl.asInstClassDecl() = this;
1630    syn InstClassDecl InstPartialFunction.asInstClassDecl()  = unknownInstClassDecl();
1631   
1632    syn InstCallable InstClassDecl.actualInstCallable()       = actualInstClass();
1633    syn InstCallable InstPartialFunction.actualInstCallable() = this;
1634   
1635    syn InstClassDecl InstClassDecl.actualInstClassDecl()       = actualInstClass();
1636    syn InstClassDecl InstPartialFunction.actualInstClassDecl() = myInstClass().actualInstClass();
1637   
1638    syn InstNode InstNode.asInstNode() = this;
1639   
1640    syn InstCallable InstFunctionCall.myInstCallable() = getName().myInstCallable();
1641   
1642    syn InstCallable InstAccess.myInstCallable() = myInstLookupCallable().target(INST_UNKNOWN_CALLABLE, this);
1643   
1644    syn InstLookupResult<InstCallable> InstAccess.myInstLookupCallable() = myInstLookup().asCallable();
1645   
1646    public InstLookupResult<InstCallable> InstLookupResult.asCallable() {
1647        if (isNotFound()) {
1648            return InstLookupResult.<InstCallable>notFound();
1649        }
1650        InstCallable ic = target().asCallable();
1651        if (ic == null) {
1652            return InstLookupResult.<InstCallable>notFound();
1653        }
1654        return create(ic);
1655    }
1656   
1657    syn InstCallable InstClassDecl.asCallable()     = this;
1658    eq InstLibNode.asCallable()                     = resolveLib();
1659    syn InstCallable InstComponentDecl.asCallable() = null;
1660    eq InstPartialFunction.asCallable()             = this;
1661}
1662
1663aspect ShortClassUtil {
1664
1665    syn InstClassDecl InstClassDecl.finalClass() = this;
1666    eq InstShortClassDecl.finalClass()           = myTargetInstClassDecl().finalClass();
1667    eq InstSimpleShortClassDecl.finalClass()     = actualInstClass().finalClass();
1668    eq InstLibNode.finalClass()                  = actualInstClass().finalClass();
1669
1670
1671    syn boolean SrcClassDecl.isInput() = false;
1672    eq SrcShortClassDecl.isInput()     = 
1673        hasInputOrOutput() && getSrcExtendsClauseShortClass().getSrcTypePrefixInputOutput().isInput();
1674
1675    syn boolean SrcClassDecl.isOutput() = false;
1676    eq SrcShortClassDecl.isOutput()     = 
1677        hasInputOrOutput() && getSrcExtendsClauseShortClass().getSrcTypePrefixInputOutput().isOutput();
1678
1679    syn boolean SrcClassDecl.hasInputOrOutput() = false;
1680    eq SrcShortClassDecl.hasInputOrOutput()     = getSrcExtendsClauseShortClass().hasSrcTypePrefixInputOutput();
1681
1682    syn boolean InstClassDecl.isInput()            = false;
1683    eq InstShortClassDecl.isInput()                = 
1684        getSrcClassDecl().isInput() || myTargetInstClassDecl().isInput();
1685    eq InstSimpleShortClassDecl.isInput()          = actualInstClass().isInput();
1686    eq InstLibNode.isInput()                       = actualInstClass().isInput();
1687    eq InstReplacingShortClassDecl.isInput()       = 
1688        (super.isInput() || super.isOutput()) ? super.isInput() : getOriginalInstClass().isInput();
1689    eq InstReplacingSimpleShortClassDecl.isInput() = 
1690        (super.isInput() || super.isOutput()) ? super.isInput() : getOriginalInstClass().isInput();
1691
1692    syn boolean InstClassDecl.isOutput()            = false;
1693    eq InstShortClassDecl.isOutput()                =
1694        getSrcClassDecl().isOutput() || myTargetInstClassDecl().isOutput();
1695    eq InstSimpleShortClassDecl.isOutput()          = actualInstClass().isOutput();
1696    eq InstLibNode.isOutput()                       = actualInstClass().isOutput();
1697    eq InstReplacingShortClassDecl.isOutput()       = 
1698        (super.isInput() || super.isOutput()) ? super.isOutput() : getOriginalInstClass().isOutput();
1699    eq InstReplacingSimpleShortClassDecl.isOutput() = 
1700        (super.isInput() || super.isOutput()) ? super.isOutput() : getOriginalInstClass().isOutput();
1701
1702    syn boolean SrcComponentDecl.isEnumLiteral() = false;
1703    eq SrcEnumLiteralDecl.isEnumLiteral() = true;
1704    syn boolean InstComponentDecl.isEnumLiteral() = false;
1705    eq InstEnumLiteral.isEnumLiteral() = true;
1706
1707}
1708
1709
1710aspect LineOffsets {
1711    private int[] SrcStoredDefinition.lineBreakMap;
1712   
1713    public void SrcStoredDefinition.setLineBreakMap(int[] map) {
1714        lineBreakMap = map;
1715    }
1716}
1717
1718
1719aspect NodeSearch {
1720   
1721    /**
1722     * Does node match <code>string</code>? Override for node types that
1723     * need to be searched for.
1724     *
1725     * Base implementation always returns <code>false</code.
1726     * Generally, this is implemented with something like
1727     * <code>str.equals(name())</code>.
1728     *
1729     * @param str  the string to match
1730     * @return     <code>true</code if <code>str</code> matches this node,
1731     *             <code>false</code> otherwise
1732     */
1733    syn boolean ASTNode.matches(String str) = false;
1734    eq SrcAccess.matches(String str)           = name().equals(str);
1735    eq InstAccess.matches(String str)       = name().equals(str);
1736   
1737   
1738    public class ASTNode {
1739       
1740        /**
1741         * Searches <code>set</code> for a node that returns <code>true</code> for
1742         * <code>node.matches(str)</code>.
1743         *
1744         * @param set  the container to search for a matching node
1745         * @param str  the string to match nodes to
1746         * @return     a matching node if one is found, <code>null</code> otherwise
1747         */
1748        public static <T extends ASTNode> T findMatching(Iterable<T> set, String str) {
1749            for (T node : set) 
1750                if (node.matches(str)) 
1751                    return node;
1752            return null;
1753        }
1754       
1755    }
1756   
1757}
1758
1759
1760aspect Strings {
1761
1762    /**
1763     * Get the value of this string literal with all escape sequences
1764     *        replaced with their actual meaning.
1765     */
1766    syn String SrcStringLitExp.unEscape() = unEscape(getSTRING());
1767
1768    /**
1769     * Get the value of this string literal with all escape sequences
1770     *        replaced with their actual meaning.
1771     */
1772    syn String FStringLitExp.unEscape() = unEscape(getString());
1773
1774    /**
1775     * Replace all escape sequences with their actual meaning.
1776     */
1777    public static String ASTNode.unEscape(String str) {
1778        return patternedReplace(str, UN_ESCAPE_PATTERN, unEscapeReplacements());
1779    }
1780
1781    /**
1782     * Replace all characters that should be escaped in a Modelica String with
1783     * their escape sequences.
1784     */
1785    public static String ASTNode.escape(String str) {
1786        return patternedReplace(str, ESCAPE_PATTERN, escapeReplacements());
1787    }
1788
1789    private static final Pattern ASTNode.UN_ESCAPE_PATTERN = Pattern.compile("\\\\(.)");
1790
1791    private static Map<String,String> ASTNode.unEscapeReplacements() {
1792        if (UN_ESCAPE_REPLACEMENTS == null) {
1793            UN_ESCAPE_REPLACEMENTS = new HashMap<String,String>();
1794            UN_ESCAPE_REPLACEMENTS.put("'", "'");
1795            UN_ESCAPE_REPLACEMENTS.put("\"", "\"");
1796            UN_ESCAPE_REPLACEMENTS.put("?", "?");
1797            UN_ESCAPE_REPLACEMENTS.put("\\", Matcher.quoteReplacement("\\"));
1798            UN_ESCAPE_REPLACEMENTS.put("a", "\007");
1799            UN_ESCAPE_REPLACEMENTS.put("b", "\b");
1800            UN_ESCAPE_REPLACEMENTS.put("f", "\f");
1801            UN_ESCAPE_REPLACEMENTS.put("n", "\n");
1802            UN_ESCAPE_REPLACEMENTS.put("r", "\r");
1803            UN_ESCAPE_REPLACEMENTS.put("v", "\013");
1804            UN_ESCAPE_REPLACEMENTS.put("t", "\t");
1805        }
1806        return UN_ESCAPE_REPLACEMENTS;
1807    }
1808
1809    private static Map<String,String> ASTNode.UN_ESCAPE_REPLACEMENTS = null;
1810
1811    private static final Pattern ASTNode.ESCAPE_PATTERN = 
1812            Pattern.compile("([\"'\\\\\007\b\f\n\r\013\t])");
1813
1814    private static Map<String,String> ASTNode.escapeReplacements() {
1815        if (ESCAPE_REPLACEMENTS == null) {
1816            ESCAPE_REPLACEMENTS = new HashMap<String,String>();
1817            ESCAPE_REPLACEMENTS.put("'",    Matcher.quoteReplacement("\\'"));
1818            ESCAPE_REPLACEMENTS.put("\"",   Matcher.quoteReplacement("\\\""));
1819            ESCAPE_REPLACEMENTS.put("\\",   Matcher.quoteReplacement("\\\\"));
1820            ESCAPE_REPLACEMENTS.put("\007", Matcher.quoteReplacement("\\a"));
1821            ESCAPE_REPLACEMENTS.put("\b",   Matcher.quoteReplacement("\\b"));
1822            ESCAPE_REPLACEMENTS.put("\f",   Matcher.quoteReplacement("\\f"));
1823            ESCAPE_REPLACEMENTS.put("\n",   Matcher.quoteReplacement("\\n"));
1824            ESCAPE_REPLACEMENTS.put("\r",   Matcher.quoteReplacement("\\r"));
1825            ESCAPE_REPLACEMENTS.put("\013", Matcher.quoteReplacement("\\v"));
1826            ESCAPE_REPLACEMENTS.put("\t",   Matcher.quoteReplacement("\\t"));
1827        }
1828        return ESCAPE_REPLACEMENTS;
1829    }
1830
1831    private static Map<String,String> ASTNode.ESCAPE_REPLACEMENTS = null;
1832
1833    private static String ASTNode.patternedReplace(
1834            String str, Pattern pattern, Map<String,String> repl) {
1835        StringBuffer buf = new StringBuffer();
1836        Matcher m = pattern.matcher(str);
1837        while (m.find())
1838            m.appendReplacement(buf, repl.get(m.group(1)));
1839        m.appendTail(buf);
1840        return buf.toString();
1841    }
1842
1843}
1844
1845
1846aspect SrcStringComments {
1847       
1848        syn boolean       SrcClassDecl.hasSrcStringComment() = false;
1849        syn SrcStringComment SrcClassDecl.getSrcStringComment() = null;
1850       
1851        eq SrcShortClassDecl.hasSrcStringComment() = getSrcExtendsClauseShortClass().getSrcComment().hasSrcStringComment();
1852        eq SrcShortClassDecl.getSrcStringComment() = getSrcExtendsClauseShortClass().getSrcComment().getSrcStringComment();
1853       
1854}
1855
1856
1857aspect Sorting {
1858   
1859        public static final Comparator<FAbstractVariable> FAbstractVariable.NAME_COMPARATOR = 
1860                new Comparator<FAbstractVariable>() {
1861                        public int compare(FAbstractVariable fv1, FAbstractVariable fv2) {
1862                                String n1 = (fv1 == null) ? null : fv1.name();
1863                                String n2 = (fv2 == null) ? null : fv2.name();
1864                                if (n1 != null)
1865                                        return n1.compareTo(n2);
1866                                else
1867                                        return (n2 != null) ? 1 : 0;
1868                        }
1869                       
1870                        public boolean equals(Object obj) { 
1871                                return obj == this; 
1872                        }
1873                };
1874           
1875                public static final Comparator<ASTNode> ASTNode.CHILD_ORDER_COMPARATOR =
1876                    new Comparator<ASTNode>() {
1877                                public int compare(ASTNode n1, ASTNode n2) {
1878                                return childIndex(n1) - childIndex(n2);
1879                            }
1880                               
1881                                private int childIndex(ASTNode n) {
1882                                        return (n.parent == null) ? 0 : n.parent.getIndexOfChild(n);
1883                                }
1884                           
1885                                public boolean equals(Object obj) { 
1886                                return obj == this; 
1887                            }
1888                        };
1889                   
1890                public static final Comparator<ASTNode> ASTNode.TOSTRING_COMPARATOR =
1891                    new Comparator<ASTNode>() {
1892                                public int compare(ASTNode n1, ASTNode n2) {
1893                                return n1.toString().compareTo(n2.toString());
1894                            }
1895                           
1896                                public boolean equals(Object obj) { 
1897                                return obj == this; 
1898                            }
1899                        };
1900
1901}
1902
1903
1904aspect GeneralHelpers {
1905
1906    abstract public FExp FExp.copy();
1907    abstract public InstAccess InstAccess.copy();
1908
1909    public FExp FExp.unboundCopy() { return (FExp) super.unboundCopy(); }
1910
1911        inh boolean ASTNode.isFirst();
1912        eq List.getChild(int i).isFirst()    = i == 0;
1913        eq ASTNode.getChild(int i).isFirst() = true;
1914       
1915        inh boolean ASTNode.isLast();
1916        eq List.getChild(int i).isLast()     = i == getNumChild() - 1;
1917        eq ASTNode.getChild(int i).isLast()  = true;
1918       
1919        public class ASTNode {
1920               
1921                /**
1922                 * Used to iterate over the children of an AST node without triggering rewrites.
1923                 */
1924                public Iterable<T> noTransform() { 
1925                        return new Iterable<T>() {
1926                                public Iterator<T> iterator() {
1927                                        return new NoTransformIterator();
1928                                }
1929                        };
1930                }
1931               
1932                /**
1933                 * Used to iterate over the children of an AST node without triggering rewrites.
1934                 */
1935                public class NoTransformIterator implements Iterator<T> {
1936                       
1937                        private int i = 0;
1938                        private int n = getNumChildNoTransform();
1939                       
1940                        public boolean hasNext() {
1941                                return i < n;
1942                        }
1943                       
1944                        public T next() {
1945                                return getChildNoTransform(i++);
1946                        }
1947                       
1948                        public void remove() {
1949                                throw new UnsupportedOperationException();
1950                        }
1951                       
1952                }
1953               
1954        }
1955
1956    /**
1957     * Adds all children to a Collection.
1958     */
1959    public void ASTNode.addAllTo(Collection<? super T> col) {
1960        for (T n : this) {
1961            col.add(n);
1962        }
1963    }
1964
1965    /**
1966     * Create an array list with all children.
1967     */
1968     public ArrayList<T> ASTNode.createArrayList() {
1969        ArrayList<T> res = new ArrayList<>(getNumChild());
1970        addAllTo(res);
1971        return res;
1972     }
1973
1974        /**
1975     * Check if this when equation is the else part of another when equation.
1976     */
1977    inh boolean FIfWhenElseEquation.isElse();
1978    eq FIfWhenEquation.getElse().isElse()    = true;
1979    eq FAbstractEquation.getChild().isElse() = false;
1980    eq FClass.getChild().isElse()            = false;
1981    eq InstNode.getChild().isElse()          = false;
1982
1983        /**
1984         * Round a number to 2 decimals if it is < 10, 1 decimal otherwise.
1985         */
1986        public static double ASTNode.roundFriendly(double val) {
1987                double round = val < 10.0 ? 100.0 : 10.0;
1988                return Math.round(val * round) / round;
1989        }
1990
1991        /**
1992         * Create a human-readable memory size string (e.g. 2.34 kB).
1993         *
1994         * @param mem  size to format, in bytes. May be negative.
1995         */
1996        public static String ASTNode.formatMem(long mem) {
1997                int i = 0;
1998                double scaledMem = Math.abs(mem);
1999                for (; i < 4 && scaledMem >= 1000.0; i++)
2000                        scaledMem /= 1024.0;
2001                StringBuilder buf = new StringBuilder();
2002                if (i == 0) {
2003                        buf.append(mem);
2004                } else {
2005                        if (mem < 0)
2006                                buf.append('-');
2007                        buf.append(roundFriendly(scaledMem));
2008                }
2009                buf.append(memUnits[i]);
2010                return buf.toString();
2011        }
2012
2013        /**
2014         * Parse a human-readable memory size string (e.g. 2.34 kB).
2015         *
2016         * @param str  string to parse
2017         * @return  the amount of memory described by the string
2018         */
2019        public static long ASTNode.parseMem(String str) {
2020                Matcher m = memPattern.matcher(str);
2021                if (m.matches()) {
2022                        double val = Double.parseDouble(m.group(1));
2023                        String suff = m.group(4);
2024                        if (suff != null && !suff.isEmpty()) {
2025                                char sc = Character.toLowerCase(suff.charAt(0));
2026                                for (int i = 0; i < memUnits.length && Character.toLowerCase(memUnits[i].charAt(1)) != sc; i++)
2027                                        val *= 1024.0;
2028                        }
2029                        if (val < Long.MAX_VALUE && val > Long.MIN_VALUE)
2030                                return (long) val;
2031                }
2032                throw new IllegalArgumentException(str);
2033        }
2034       
2035        private static final String[] ASTNode.memUnits = { 
2036                " B", " kB", " MB", " GB", " TB" , " PB" , " EB" };
2037        private static final Pattern ASTNode.memPattern = 
2038                        Pattern.compile("([0-9]+(\\.[0-9]*)?)(([kKmMgGtTpPeE])?[bB]?)?");
2039
2040}
2041
2042aspect DebugHelpers {
2043
2044        /**
2045         * Check if the list contains an instance of the specified class.
2046         */
2047        public boolean List.containsInstance(Class c) {
2048                 for (ASTNode n : children)
2049                         if (c.isInstance(n))
2050                                 return true;
2051                 return false;
2052        }
2053
2054}
Note: See TracBrowser for help on using the repository browser.