001/** Base class for structured type.
002
003 Copyright (c) 1997-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027
028 */
029package ptolemy.data.type;
030
031import ptolemy.kernel.util.IllegalActionException;
032
033///////////////////////////////////////////////////////////////////
034//// StructuredType
035
036/**
037 Base class for structured type. Making this an abstract class (not an
038 interface) allows the methods to be protected.
039 All the types of the same structured type (e.g. all the array types)
040 must form a lattice. Each instance of a structured type must know how
041 to compare itself with another instance of the same structured type,
042 and compute the least upper bound and greatest lower bound. This
043 class defines methods for these operations.
044 <p>
045 Subclasses should override clone() to do a deep cloning.
046
047 @author Yuhong Xiong, Steve Neuendorffer
048 @version $Id$
049 @since Ptolemy II 0.4
050 @Pt.ProposedRating Red (yuhong)
051 @Pt.AcceptedRating Red (cxh)
052 */
053public abstract class StructuredType implements Type {
054    ///////////////////////////////////////////////////////////////////
055    ////                         public methods                    ////
056
057    /** Return a new type which represents the type that results from
058     *  adding a token of this type and a token of the given argument
059     *  type.
060     *  @param rightArgumentType The type to add to this type.
061     *  @return A new type, or BaseType.GENERAL, if the operation does
062     *  not make sense for the given types.
063     */
064    @Override
065    public Type add(Type rightArgumentType) {
066        return TypeLattice.leastUpperBound(this, rightArgumentType);
067    }
068
069    /** Return a deep copy of this StructuredType.
070     *  @return A StructuredType.
071     *  @exception CloneNotSupportedException Not thrown in this base class.
072     */
073    @Override
074    abstract public Object clone() throws CloneNotSupportedException;
075
076    /** Return a new type which represents the type that results from
077     *  dividing a token of this type and a token of the given
078     *  argument type.
079     *  @param rightArgumentType The type to divide with this type.
080     *  @return A new type, or BaseType.GENERAL, if the operation does
081     *  not make sense for the given types.
082     */
083    @Override
084    public Type divide(Type rightArgumentType) {
085        return TypeLattice.leastUpperBound(this, rightArgumentType);
086    }
087
088    /** Return the depth of a structured type. The depth of a
089     *  structured type is the number of times a structured type
090     *  contains other structured types. For example, an array
091     *  of arrays has depth 2, and an array of arrays of records
092     *  has depth 3.
093     *  @return the depth of a structured type.
094     */
095    public int depth() {
096        return 1;
097    }
098
099    /** Return a perfect hash for this type.  This number corresponds
100     *  uniquely to a particular type, and is used to improve
101     *  performance of certain operations in the TypeLattice class.
102     *  All instances of a particular type (e.g. integer array) must
103     *  return the same number.  Types that return HASH_INVALID will
104     *  not have results in TypeLattice cached.  Note that it is safer
105     *  to return HASH_INVALID, than to return a number that is not
106     *  unique, or different number for the same type from different
107     *  instances.  This base class returns HASH_INVALID.
108     *  @return A number greater than or equal to 0, or HASH_INVALID.
109     */
110    @Override
111    public int getTypeHash() {
112        return Type.HASH_INVALID;
113    }
114
115    /** Return true if this type does not correspond to a single token
116     *  class.  This occurs if the type is not instantiable, or it
117     *  represents either an abstract base class or an interface.
118     *  This method should be overridden in derived classes to return
119     *  true only for types which are not abstract.
120     *  @return true.
121     */
122    @Override
123    public boolean isAbstract() {
124        return true;
125
126    }
127
128    /** Set the elements that have declared type BaseType.UNKNOWN to the
129     *  specified type.
130     *  @param type A Type.
131     */
132    public abstract void initialize(Type type);
133
134    /** Return a new type which represents the type that results from
135     *  moduloing a token of this type and a token of the given
136     *  argument type.
137     *  @param rightArgumentType The type to add to this type.
138     *  @return A new type, or BaseType.GENERAL, if the operation does
139     *  not make sense for the given types.
140     */
141    @Override
142    public Type modulo(Type rightArgumentType) {
143        return TypeLattice.leastUpperBound(this, rightArgumentType);
144    }
145
146    /** Return a new type which represents the type that results from
147     *  multiplying a token of this type and a token of the given
148     *  argument type.
149     *  @param rightArgumentType The type to multiply by this type.
150     *  @return A new type, or BaseType.GENERAL, if the operation does
151     *  not make sense for the given types.
152     */
153    @Override
154    public Type multiply(Type rightArgumentType) {
155        return TypeLattice.leastUpperBound(this, rightArgumentType);
156    }
157
158    /** Return the type of the multiplicative identity for elements of
159     *  this type.
160     *  @return A new type, or BaseType.GENERAL, if the operation does
161     *  not make sense for the given types.
162     */
163    @Override
164    public Type one() {
165        return this;
166    }
167
168    /** Return a new type which represents the type that results from
169     *  subtracting a token of this type and a token of the given
170     *  argument type.
171     *  @param rightArgumentType The type to add to this type.
172     *  @return A new type, or BaseType.GENERAL, if the operation does
173     *  not make sense for the given types.
174     */
175    @Override
176    public Type subtract(Type rightArgumentType) {
177        return TypeLattice.leastUpperBound(this, rightArgumentType);
178    }
179
180    /** Update this StructuredType to the specified Structured Type.
181     *  The specified type must have depth less than the MAXDEPTHBOUND, and
182     *  have the same structure as this type.
183     *  This method will only update the component type that is
184     *  BaseType.UNKNOWN, and leave the constant part of this type intact.
185     *  @param newType A StructuredType.
186     *  @exception IllegalActionException If the specified type has a
187     *   different structure.
188     */
189    public void updateType(StructuredType newType)
190            throws IllegalActionException {
191        if (newType.depth() >= MAXDEPTHBOUND) {
192            throw new IllegalActionException(
193                    "Large type structure detected during type resolution."
194                            + "  The structured type " + newType.toString()
195                            + " has depth larger than the bound "
196                            + MAXDEPTHBOUND
197                            + ".  This may be an indicator of type constraints "
198                            + "in a model with no finite solution.");
199        }
200    }
201
202    /** Return the type of the additive identity for elements of
203     *  this type.
204     *  @return A new type, or BaseType.GENERAL, if the operation does
205     *  not make sense for the given types.
206     */
207    @Override
208    public Type zero() {
209        return this;
210    }
211
212    ///////////////////////////////////////////////////////////////////
213    ////                         protected methods                 ////
214
215    /** Compare this type with the specified type. The specified type
216     *  must be of the same structured type, otherwise an exception will
217     *  be thrown.
218     *  This method returns one of ptolemy.graph.CPO.LOWER,
219     *  ptolemy.graph.CPO.SAME, ptolemy.graph.CPO.HIGHER,
220     *  ptolemy.graph.CPO.INCOMPARABLE, indicating this type is lower
221     *  than, equal to, higher than, or incomparable with the
222     *  specified type in the type hierarchy, respectively.
223     *  @param type a StructuredType.
224     *  @return An integer.
225     *  @exception IllegalArgumentException If the specified type is
226     *   not the same structured type as this one.
227     */
228    protected abstract int _compare(StructuredType type);
229
230    /** Return a static instance of this structured type. The return
231     *  value is used by TypeLattice to represent this type.
232     *  @return a StructuredType.
233     */
234    protected abstract StructuredType _getRepresentative();
235
236    /** Return the greatest lower bound of this type with the specified
237     *  type. The specified type must be of the same structured type,
238     *  otherwise an exception will be thrown.
239     *  @param type a StructuredType.
240     *  @return a StructuredType.
241     *  @exception IllegalArgumentException If the specified type is
242     *   not the same structured type as this one.
243     */
244    protected abstract StructuredType _greatestLowerBound(StructuredType type);
245
246    /** Return the least upper bound of this type with the specified
247     *  type. The specified type must be of the same structured type,
248     *  otherwise an exception will be thrown.
249     *  @param type a StructuredType.
250     *  @return a StructuredType.
251     *  @exception IllegalArgumentException If the specified type is
252     *   not the same structured type as this one.
253     */
254    protected abstract StructuredType _leastUpperBound(StructuredType type);
255
256    /** Set up a bound for the max depth of structured types. This bound
257     *  is used to detect infinite iterations.
258     */
259    protected static final int MAXDEPTHBOUND = 20;
260}