001/* The type of base token classes.
002
003 Copyright (c) 1997-2018 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 */
028package ptolemy.data.type;
029
030import java.lang.reflect.Modifier;
031import java.util.HashMap;
032import java.util.Map;
033
034import ptolemy.data.ActorToken;
035import ptolemy.data.BooleanToken;
036import ptolemy.data.ComplexToken;
037import ptolemy.data.DateToken;
038import ptolemy.data.DoubleToken;
039import ptolemy.data.EventToken;
040import ptolemy.data.FixToken;
041import ptolemy.data.FloatToken;
042import ptolemy.data.IntToken;
043import ptolemy.data.LongToken;
044import ptolemy.data.MatrixToken;
045import ptolemy.data.PetiteToken;
046import ptolemy.data.ScalarToken;
047import ptolemy.data.ShortToken;
048import ptolemy.data.StringToken;
049import ptolemy.data.Token;
050import ptolemy.data.UnsignedByteToken;
051import ptolemy.data.XMLToken;
052import ptolemy.graph.CPO;
053import ptolemy.kernel.util.IllegalActionException;
054
055///////////////////////////////////////////////////////////////////
056//// BaseType
057
058/**
059 The type of base token classes. This class provides a type safe
060 enumeration of base types.
061
062 @author Yuhong Xiong, Steve Neuendorffer
063 @version $Id$
064 @since Ptolemy II 0.4
065 @Pt.ProposedRating Red (yuhong)
066 @Pt.AcceptedRating Red
067 */
068public abstract class BaseType implements Type {
069    ///////////////////////////////////////////////////////////////////
070    ////                         public methods                    ////
071
072    /** Return a new type which represents the type that results from
073     *  adding a token of this type and a token of the given argument
074     *  type.
075     *  @param rightArgumentType The type to add to this type.
076     *  @return A new type, or BaseType.GENERAL, if the operation does
077     *  not make sense for the given types.
078     */
079    @Override
080    public Type add(Type rightArgumentType) {
081        return TypeLattice.leastUpperBound(this, rightArgumentType);
082    }
083
084    /** Specify that the given type, with the given name, is implemented
085     *  by the specified token class.  Normally, an end user won't need
086     *  this method, but there is a particular use that can sometimes
087     *  come in handy. Occasionally it is useful for a token that subclasses a
088     *  standard token to be used in place of that standard token.
089     *  For example, you could create a subclass of DoubleToken called
090     *  DoublePlusPlus that includes some extra fields. For that class
091     *  to be acceptable to the expression language, for example as a return
092     *  type from a function, then you must call this method to register that
093     *  class.  In this case, you call it with arguments BaseType.DOUBLE,
094     *  "doublePlusPlus" (or whatever name you choose), and
095     *  DoublePlusPlus.class.
096     *  @param type The type.
097     *  @param name The name of the type.
098     *  @param theClass The implementation (token class) for the type.
099     */
100    public static void addType(Type type, String name, Class theClass) {
101        _addType(type, name, theClass);
102    }
103
104    /** Return this, that is, return the reference to this object.
105     *  @return A BaseType.
106     */
107    @Override
108    public Object clone() {
109        return this;
110    }
111
112    /** Convert the specified token to a token having the type
113     *  represented by this object.
114     *  @param t A token.
115     *  @return A token.
116     *  @exception IllegalActionException If lossless conversion cannot
117     *   be done.
118     */
119    @Override
120    public abstract Token convert(Token t) throws IllegalActionException;
121
122    /** Return a new type which represents the type that results from
123     *  dividing a token of this type and a token of the given
124     *  argument type.
125     *  @param rightArgumentType The type to add to this type.
126     *  @return A new type, or BaseType.GENERAL, if the operation does
127     *  not make sense for the given types.
128     */
129    @Override
130    public Type divide(Type rightArgumentType) {
131        return TypeLattice.leastUpperBound(this, rightArgumentType);
132    }
133
134    /** Determine if the argument represents the same BaseType as this
135     *  object.
136     *  @param object Another object.
137     *  @return True if the argument represents the same BaseType as
138     *   this object; false otherwise.
139     */
140    @Override
141    public boolean equals(Object object) {
142        // since BaseType is a type safe enumeration, can use == to
143        // test equality.
144        return this == object;
145    }
146
147    /** Return an instance of Type of that corresponds to tokens
148     *  of a class with the given name, or null if none exists.
149     *  @param className The name of the class.
150     *  @return An instance of BaseType.
151     */
152    public static Type forClassName(String className) {
153        return (Type) _classNameToType.get(className);
154    }
155
156    /** Return an instance of this class with the specified name,
157     *  or null if none exists. Note that this does not recognize
158     *  all the types that have symbolic names. It is better to
159     *  use ptolemy.data.expr.Constants.types() to map a name
160     *  to a type.
161     *  @param name The name of the type.
162     *  @return An instance of BaseType.
163     */
164    public static Type forName(String name) {
165        return (Type) _nameToType.get(name);
166    }
167
168    /** Return the class for tokens that this basetype represents.
169     *  @return The class for tokens that this type represents.
170     */
171    @Override
172    public Class getTokenClass() {
173        return _tokenClass;
174    }
175
176    /** Return a perfect hash for this type.  This number corresponds
177     *  uniquely to a particular type, and is used to improve
178     *  performance of certain operations in the TypeLattice class.
179     *  All instances of a particular type (e.g. integer array) must
180     *  return the same number.  Types that return HASH_INVALID will
181     *  not have results in TypeLattice cached.  Note that it is safer
182     *  to return HASH_INVALID, than to return a number that is not
183     *  unique, or different number for the same type from different
184     *  instances.  This base class returns HASH_INVALID.
185     *  @return A number greater than or equal to 0, or HASH_INVALID.
186     */
187    @Override
188    public int getTypeHash() {
189        return Type.HASH_INVALID;
190    }
191
192    /** Return a hash code value for this object.
193     */
194    @Override
195    public int hashCode() {
196        return super.hashCode();
197    }
198
199    /** Return a new type which represents the type that results from
200     *  moduloing a token of this type and a token of the given
201     *  argument type.
202     *  @param rightArgumentType The type to add to this type.
203     *  @return A new type, or BaseType.GENERAL, if the operation does
204     *  not make sense for the given types.
205     */
206    @Override
207    public Type modulo(Type rightArgumentType) {
208        return TypeLattice.leastUpperBound(this, rightArgumentType);
209    }
210
211    /** Return a new type which represents the type that results from
212     *  multiplying a token of this type and a token of the given
213     *  argument type.
214     *  @param rightArgumentType The type to add to this type.
215     *  @return A new type, or BaseType.GENERAL, if the operation does
216     *  not make sense for the given types.
217     */
218    @Override
219    public Type multiply(Type rightArgumentType) {
220        return TypeLattice.leastUpperBound(this, rightArgumentType);
221    }
222
223    /** Return true if this type does not correspond to a single token
224     *  class.  This occurs if the type is not instantiable, or it
225     *  represents either an abstract base class or an interface.
226     */
227    @Override
228    public boolean isAbstract() {
229        if (!isInstantiable()) {
230            return true;
231        }
232
233        int mod = _tokenClass.getModifiers();
234
235        if (Modifier.isAbstract(mod)) {
236            return true;
237        }
238
239        if (_tokenClass.isInterface()) {
240            return true;
241        }
242        return false;
243    }
244
245    /** Test if the argument type is compatible with this type. The method
246     *  returns true if this type is UNKNOWN, since any type is a substitution
247     *  instance of it. If this type is not UNKNOWN, this method returns true
248     *  if the argument type is less than or equal to this type in the type
249     *  lattice, and false otherwise.
250     *  @param type An instance of Type.
251     *  @return True if the argument is compatible with this type.
252     */
253    @Override
254    public boolean isCompatible(Type type) {
255        if (this == UNKNOWN) {
256            return true;
257        }
258
259        int typeInfo = TypeLattice.compare(this, type);
260        return typeInfo == CPO.SAME || typeInfo == CPO.HIGHER;
261    }
262
263    /** Test if this Type is UNKNOWN.
264     *  @return True if this Type is not UNKNOWN; false otherwise.
265     */
266    @Override
267    public boolean isConstant() {
268        return this != UNKNOWN;
269    }
270
271    /** Determine if this type corresponds to an instantiable token
272     *  classes. A BaseType is instantiable if it does not correspond
273     *  to an abstract token class, or an interface, or UNKNOWN.
274     *  @return True if this type is instantiable.
275     */
276    @Override
277    public boolean isInstantiable() {
278        if (this == UNKNOWN) {
279            return false;
280        }
281
282        return true;
283    }
284
285    /** Return true if the argument is a substitution instance of this type.
286     *  @param type A Type.
287     *  @return True if this type is UNKNOWN; false otherwise.
288     */
289    @Override
290    public boolean isSubstitutionInstance(Type type) {
291        return this == UNKNOWN || this == type;
292    }
293
294    /** Return the type of the multiplicative identity for elements of
295     *  this type.
296     *  @return A new type, or BaseType.GENERAL, if the operation does
297     *  not make sense for the given types.
298     */
299    @Override
300    public Type one() {
301        return this;
302    }
303
304    /** Return a new type which represents the type that results from
305     *  subtracting a token of this type and a token of the given
306     *  argument type.
307     *  @param rightArgumentType The type to add to this type.
308     *  @return A new type, or BaseType.GENERAL, if the operation does
309     *  not make sense for the given types.
310     */
311    @Override
312    public Type subtract(Type rightArgumentType) {
313        return TypeLattice.leastUpperBound(this, rightArgumentType);
314    }
315
316    /** Return the string representation of this type.
317     *  @return A String.
318     */
319    @Override
320    public String toString() {
321        return _name;
322    }
323
324    /** Return the type of the additive identity for elements of
325     *  this type.
326     *  @return A new type, or BaseType.GENERAL, if the operation does
327     *  not make sense for the given types.
328     */
329    @Override
330    public Type zero() {
331        return this;
332    }
333
334    ///////////////////////////////////////////////////////////////////
335    ////                         inner classes                     ////
336    // NOTE: It may seem strange that these inner classes are built this
337    // way instead of as anonymous classes...  As anonymous classes, the
338    // fields cannot be appropriately typed, which makes type inference
339    // much more complex to find the same information.  This is important
340    // to the code generator.
341
342    /** The bottom element of the data type lattice. It represents a
343     *  type variable.
344     */
345    public static class UnknownType extends BaseType {
346        private UnknownType() {
347            super(Void.TYPE, "unknown");
348        }
349
350        @Override
351        public Token convert(Token t) throws IllegalActionException {
352            // Since any type is a substitution instance of UNKNOWN, just
353            // return the argument.
354            return t;
355        }
356
357        @Override
358        public int getTypeHash() {
359            return 0;
360        }
361    }
362
363    /** The bottom element of the data type lattice. */
364    public static final UnknownType UNKNOWN = new UnknownType();
365
366    /** The bottom element of the array type lattice. */
367    public static class ArrayBottomType extends BaseType {
368        private ArrayBottomType() {
369            super(Void.TYPE, "arrayBottom");
370        }
371
372        @Override
373        public Token convert(Token t) throws IllegalActionException {
374            // Since any type is a substitution instance of UNKNOWN, just
375            // return the argument.
376            return t;
377        }
378    }
379
380    /** The bottom element of the array type lattice. */
381    public static final ArrayBottomType ARRAY_BOTTOM = new ArrayBottomType();
382
383    /** The boolean data type. */
384    public static class BooleanType extends BaseType {
385        private BooleanType() {
386            super(BooleanToken.class, "boolean");
387        }
388
389        @Override
390        public Token convert(Token t) throws IllegalActionException {
391            return BooleanToken.convert(t);
392        }
393
394        @Override
395        public int getTypeHash() {
396            return 1;
397        }
398    }
399
400    /** The boolean data type. */
401    public static final BooleanType BOOLEAN = new BooleanType();
402
403    /** The boolean matrix data type. */
404    public static final MatrixType.BooleanMatrixType BOOLEAN_MATRIX = new MatrixType.BooleanMatrixType();
405
406    /** The unsigned byte data type. */
407    public static class UnsignedByteType extends BaseType {
408        private UnsignedByteType() {
409            super(UnsignedByteToken.class, "unsignedByte");
410        }
411
412        @Override
413        public Token convert(Token t) throws IllegalActionException {
414            return UnsignedByteToken.convert(t);
415        }
416
417        @Override
418        public int getTypeHash() {
419            return 2;
420        }
421    }
422
423    /** The unsigned byte data type. */
424    public static final UnsignedByteType UNSIGNED_BYTE = new UnsignedByteType();
425
426    /** The complex data type. */
427    public static class ComplexType extends BaseType {
428        private ComplexType() {
429            super(ComplexToken.class, "complex");
430        }
431
432        @Override
433        public Token convert(Token t) throws IllegalActionException {
434            return ComplexToken.convert(t);
435        }
436
437        @Override
438        public int getTypeHash() {
439            return 3;
440        }
441    }
442
443    /** The complex data type. */
444    public static final ComplexType COMPLEX = new ComplexType();
445
446    /** The complex matrix data type. */
447    public static final MatrixType.ComplexMatrixType COMPLEX_MATRIX = new MatrixType.ComplexMatrixType();
448
449    /** The float data type. */
450    public static class FloatType extends BaseType {
451        private FloatType() {
452            super(FloatToken.class, "float");
453        }
454
455        @Override
456        public Token convert(Token t) throws IllegalActionException {
457            return FloatToken.convert(t);
458        }
459
460        @Override
461        public int getTypeHash() {
462            return 16;
463        }
464    }
465
466    /** The float data type. */
467    public static final FloatType FLOAT = new FloatType();
468
469    /** The double data type. */
470    public static class DoubleType extends BaseType {
471        private DoubleType() {
472            super(DoubleToken.class, "double");
473        }
474
475        @Override
476        public Token convert(Token t) throws IllegalActionException {
477            return DoubleToken.convert(t);
478        }
479
480        @Override
481        public int getTypeHash() {
482            return 4;
483        }
484    }
485
486    /** The double data type. */
487    public static final DoubleType DOUBLE = new DoubleType();
488
489    /** The double matrix data type. */
490    public static final MatrixType.DoubleMatrixType DOUBLE_MATRIX = new MatrixType.DoubleMatrixType();
491
492    /** The fix data type. */
493    public static class UnsizedFixType extends BaseType {
494        private UnsizedFixType() {
495            super(FixToken.class, "fixedpoint");
496        }
497
498        @Override
499        public Token convert(Token t) throws IllegalActionException {
500            if (t instanceof FixToken) {
501                return t;
502            } else {
503                throw new IllegalActionException(
504                        "Cannot convert token " + t + " to type fixed point.");
505            }
506        }
507    }
508
509    /** An alias for the unsized fix data type, provided for backward
510     * compatibility with the previous versions of Ptolemy.
511     */
512    public static final UnsizedFixType FIX = new UnsizedFixType();
513
514    /** The unsized fix data type. */
515    public static final UnsizedFixType UNSIZED_FIX = FIX;
516
517    /** The fix data type, with a precision specified. */
518    public static final FixType SIZED_FIX = FixType.BOTTOM;
519
520    /** The fix matrix data type. */
521    public static final MatrixType.FixMatrixType FIX_MATRIX = new MatrixType.FixMatrixType();
522
523    /** The short integer data type. */
524    public static class ShortType extends BaseType {
525        private ShortType() {
526            super(ShortToken.class, "short");
527        }
528
529        @Override
530        public Token convert(Token t) throws IllegalActionException {
531            return ShortToken.convert(t);
532        }
533
534        @Override
535        public int getTypeHash() {
536            return 15;
537        }
538    }
539
540    /** The short integer data type. */
541    public static final ShortType SHORT = new ShortType();
542
543    /** The integer data type. */
544    public static class IntType extends BaseType {
545        private IntType() {
546            super(IntToken.class, "int");
547        }
548
549        @Override
550        public Token convert(Token t) throws IllegalActionException {
551            return IntToken.convert(t);
552        }
553
554        @Override
555        public int getTypeHash() {
556            return 5;
557        }
558    }
559
560    /** The integer data type. */
561    public static final IntType INT = new IntType();
562
563    /** The integer matrix data type. */
564    public static final MatrixType.IntMatrixType INT_MATRIX = new MatrixType.IntMatrixType();
565
566    /** The long integer data type. */
567    public static class LongType extends BaseType {
568        private LongType() {
569            super(LongToken.class, "long");
570        }
571
572        @Override
573        public Token convert(Token t) throws IllegalActionException {
574            return LongToken.convert(t);
575        }
576
577        @Override
578        public int getTypeHash() {
579            return 6;
580        }
581    }
582
583    /** The long integer data type. */
584    public static final LongType LONG = new LongType();
585
586    /** The long integer matrix data type. */
587    public static final MatrixType.LongMatrixType LONG_MATRIX = new MatrixType.LongMatrixType();
588
589    /** The numerical data type. */
590    // NOTE: Removed NUMERICAL from the type lattice, EAL 6/22/06.
591    /*
592     public static class NumericalType extends BaseType {
593     private NumericalType() {
594     super(Numerical.class, "numerical");
595     }
596
597     public Token convert(Token t) throws IllegalActionException {
598     throw new IllegalActionException(
599     "Cannot convert token "
600     + t
601     + " to type numerical, because numerical is not a concrete type.");
602     }
603
604     public int getTypeHash() {
605     return 7;
606     }
607     }
608     */
609
610    /** The numerical data type. */
611    // NOTE: Removed NUMERICAL from the type lattice, EAL 6/22/06.
612    /*
613     public static final NumericalType NUMERICAL = new NumericalType();
614     */
615
616    /** The object data type. */
617    public static final ObjectType OBJECT = new ObjectType();
618
619    /** The actor data type. */
620    public static final Type ACTOR = ActorToken.TYPE;
621
622    /** The XmlToken data type. */
623    public static class XmlTokenType extends BaseType {
624        private XmlTokenType() {
625            super(XMLToken.class, "xmltoken");
626        }
627
628        @Override
629        public Token convert(Token t) throws IllegalActionException {
630            return XMLToken.convert(t);
631        }
632
633        @Override
634        public int getTypeHash() {
635            return 8;
636        }
637    }
638
639    /** The XmlToken data type. */
640    public static final XmlTokenType XMLTOKEN = new XmlTokenType();
641
642    /** The scalar data type: The least upper bound of all the scalar types. */
643    public static class ScalarType extends BaseType {
644        private ScalarType() {
645            super(ScalarToken.class, "scalar");
646        }
647
648        @Override
649        public Token convert(Token t) throws IllegalActionException {
650            if (t instanceof ScalarToken) {
651                return t;
652            }
653            throw new IllegalActionException(Token
654                    .notSupportedIncomparableConversionMessage(t, "scalar"));
655        }
656
657        @Override
658        public int getTypeHash() {
659            return 9;
660        }
661
662        //         public boolean isInstantiable() {
663        //             return true;
664        //         }
665    }
666
667    /** The scalar data type: The least upper bound of all the scalar types. */
668    public static final ScalarType SCALAR = new ScalarType();
669
670    /** The matrix data type: The least upper bound of all the matrix types. */
671    public static final MatrixType MATRIX = new MatrixType(MatrixToken.class,
672            SCALAR, "matrix");
673
674    /** The string data type. */
675    public static class StringType extends BaseType {
676        private StringType() {
677            super(StringToken.class, "string");
678        }
679
680        @Override
681        public Token convert(Token t) throws IllegalActionException {
682            return StringToken.convert(t);
683        }
684
685        @Override
686        public int getTypeHash() {
687            return 10;
688        }
689    }
690
691    /** The string data type. */
692    public static final StringType STRING = new StringType();
693
694    /** The general data type: The top of the lattice.  */
695    public static class GeneralType extends BaseType {
696        private GeneralType() {
697            super(Token.class, "general");
698        }
699
700        @Override
701        public Token convert(Token t) throws IllegalActionException {
702            return t;
703        }
704
705        @Override
706        public int getTypeHash() {
707            return 11;
708        }
709    }
710
711    /** The general data type: The top of the lattice.  */
712    public static final GeneralType GENERAL = new GeneralType();
713
714    /** The event data type. */
715    public static class EventType extends BaseType {
716        private EventType() {
717            super(EventToken.class, "event");
718        }
719
720        @Override
721        public Token convert(Token t) throws IllegalActionException {
722            return t;
723        }
724
725        @Override
726        public int getTypeHash() {
727            return 12;
728        }
729    }
730
731    /** The event data type. */
732    public static final EventType EVENT = new EventType();
733
734    /** The petite data type. */
735    public static class PetiteType extends BaseType {
736        private PetiteType() {
737            super(PetiteToken.class, "petite");
738        }
739
740        @Override
741        public Token convert(Token t) throws IllegalActionException {
742            return PetiteToken.convert(t);
743        }
744
745        @Override
746        public int getTypeHash() {
747            return 13;
748        }
749    }
750
751    /** The petite data type. */
752    public static final PetiteType PETITE = new PetiteType();
753
754    /** The nil data type. */
755    public static class NilType extends BaseType {
756        private NilType() {
757            super(Token.class, "niltype");
758        }
759
760        @Override
761        public Token convert(Token t) throws IllegalActionException {
762            return t;
763        }
764
765        @Override
766        public int getTypeHash() {
767            return 14;
768        }
769    }
770
771    /** The nil data type. */
772    public static final NilType NIL = new NilType();
773
774    /** The date data type. */
775    public static class DateType extends BaseType {
776        private DateType() {
777            super(DateToken.class, "date");
778        }
779
780        @Override
781        public Token convert(Token t) throws IllegalActionException {
782            return DateToken.convert(t);
783        }
784
785        @Override
786        public int getTypeHash() {
787            return 16;
788        }
789    }
790
791    /** The DateToken data type. */
792    public static final DateType DATE = new DateType();
793
794    ///////////////////////////////////////////////////////////////////
795    ////                    package private method                 ////
796
797    /** Add entries in this class to index the given name and class to
798     *  the given type.
799     *  @param type The type.
800     *  @param name The name of the type.
801     *  @param theClass The implementation (token class) for the type.
802     */
803    static void _addType(Type type, String name, Class theClass) {
804        // Because the private variables are below the public variables
805        // that call this initializer,
806        // it doesn't work to initialize this statically.
807        if (_nameToType == null) {
808            _nameToType = new HashMap();
809        }
810
811        if (_classNameToType == null) {
812            _classNameToType = new HashMap();
813        }
814
815        _nameToType.put(name, type);
816        _classNameToType.put(theClass.getName(), type);
817    }
818
819    /** Setting the type of something to RECORD allows it to take
820     *  on a value that is any record with any fields. This is because
821     *  a lossless conversion any such record to an empty record just
822     *  returns the original record.  So to force something to have a
823     *  record type without specifying what fields it should have, do
824     *  <pre>
825     *    something.setTypeEquals(BaseType.RECORD);
826     *  </pre>
827     *  To allow the type to resolve to a specific record type (with
828     *  particular fields), do instead
829     *  <pre>
830     *    something.setTypeAtMost(BaseType.RECORD);
831     *  </pre>
832     *  This will work for example to require a parameter to have a record
833     *  value, but to allow its type to resolve to the specific record
834     *  specified.
835     */
836    static public final RecordType RECORD = RecordType.EMPTY_RECORD;
837
838    ///////////////////////////////////////////////////////////////////
839    ////                      private constructor                  ////
840
841    /** The constructor is private to make a type safe enumeration. */
842    private BaseType(Class c, String name) {
843        _tokenClass = c;
844        _name = name;
845        _addType(this, name, c);
846    }
847
848    ///////////////////////////////////////////////////////////////////
849    ////                         private variables                 ////
850
851    /** The class of tokens with this type. */
852    private Class _tokenClass;
853
854    /** The name of the type. */
855    private String _name;
856
857    /** A map from type name to the type for all base types. */
858    private static Map _nameToType;
859
860    /** A map from class name to the type for all base types. */
861    private static Map _classNameToType;
862}