0001: /*
0002: * xtc - The eXTensible Compiler
0003: * Copyright (C) 2005-2007 Robert Grimm
0004: *
0005: * This program is free software; you can redistribute it and/or
0006: * modify it under the terms of the GNU General Public License
0007: * version 2 as published by the Free Software Foundation.
0008: *
0009: * This program is distributed in the hope that it will be useful,
0010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0012: * GNU General Public License for more details.
0013: *
0014: * You should have received a copy of the GNU General Public License
0015: * along with this program; if not, write to the Free Software
0016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
0017: * USA.
0018: */
0019: package xtc.type;
0020:
0021: import java.math.BigInteger;
0022:
0023: import java.util.ArrayList;
0024: import java.util.Collections;
0025: import java.util.List;
0026: import java.util.Set;
0027:
0028: import xtc.Constants;
0029:
0030: import xtc.tree.Attribute;
0031: import xtc.tree.Location;
0032: import xtc.tree.Locatable;
0033: import xtc.tree.Node;
0034: import xtc.tree.Visitor;
0035:
0036: import xtc.util.Runtime;
0037:
0038: /**
0039: * The superclass of all types.
0040: *
0041: * <p />The class hierarchy for types distinguishes basic from wrapped
0042: * types, with wrapped types providing additional information for
0043: * basic types. For each basic type, this class provides
0044: * <code>is<i>Name</i>()</code> and <code>to<i>Name</i>()</code>
0045: * methods to replace instanceof tests and casts, respectively. For
0046: * each wrapped type, this class additionally provides a
0047: * <code>has<i>Name</i>()</code> method, which identifies instances of
0048: * the wrapped type even if they are wrapped inside another (wrapped)
0049: * type. In other words, invocations of <code>has<i>Name</i>()</code>
0050: * are forwarded across wrapped types while invocations of
0051: * <code>is<i>Name</i>()</code> only apply to the outermost type
0052: * object. For wrapped types, invocations of
0053: * <code>to<i>Name</i>()</code> are also forwarded across (other)
0054: * wrapped types.
0055: *
0056: * <p />As an example, consider an int type wrapped in an annotated
0057: * type and an alias type:
0058: * <pre>
0059: * Type i = NumberT.INT;
0060: * Type j = new AnnotatedT(i);
0061: * Type k = new AliasT("alias", j);
0062: * </pre>
0063: * Then the following method invocations have the following results:
0064: * <pre>
0065: * k.isAlias() ⇒ <i>true</i>
0066: * k.hasAlias() ⇒ <i>true</i>
0067: * k.toAlias() ⇒ <i>k</i>
0068: *
0069: * k.isAnnotated() ⇒ <i>false</i>
0070: * k.hasAnnotated() ⇒ <i>true</i>
0071: * k.toAnnotated() ⇒ <i>j</i>
0072: *
0073: * k.isInteger() ⇒ <i>false</i>
0074: * k.toInteger() ⇒ <i>error</i>
0075: * </pre>
0076: * The {@link #resolve()} method can be used to strip any wrapped
0077: * types:
0078: * <pre>
0079: * Type r = k.resolve();
0080: *
0081: * r.isAlias() ⇒ <i>false</i>
0082: * r.isAnnotated() ⇒ <i>false</i>
0083: * r.isInteger() ⇒ <i>true</i>
0084: * r.toInteger() ⇒ <i>i</i>
0085: * </pre>
0086: *
0087: * <p />The {@link Tag} enumeration also identifies particular types.
0088: * A type's tag can be accessed through {@link #tag()}, which is
0089: * forwarded across wrapped types, and through {@link #wtag()}, which
0090: * is <em>not</em> forwarded across wrapped types. As a result,
0091: * <code>tag()</code> identifies basic types independent of whether
0092: * they are wrapped or not, while <code>wtag()</code> always
0093: * identifies the outermost type:
0094: * <pre>
0095: * k.tag() ⇒ <i>Tag.INTEGER</i>
0096: * k.wtag() ⇒ <i>Tag.ALIAS</i>
0097: *
0098: * i.tag() ⇒ <i>Tag.INTEGER</i>
0099: * i.tag() ⇒ <i>Tag.INTEGER</i>
0100: * </pre>
0101: *
0102: * <p />Each type can have one or more of the following
0103: * annotations:<ul>
0104: *
0105: * <li>Its source location represented as a {@link Location}.</li>
0106: *
0107: * <li>Its source language represented as a {@link Language} tag.</li>
0108: *
0109: * <li>Its scope represented as a {@link String}.</li>
0110: *
0111: * <li>Its constant value represented as a {@link Constant}.</li>
0112: *
0113: * <li>Its memory shape represented as a {@link Reference}. Only
0114: * lvalues can have a shape.</li>
0115: *
0116: * <li>Its attributes represented as a list of {@link Attribute}
0117: * values.</li>
0118: *
0119: * </ul>
0120: * For each kind of annotation, this class defines tester, getter, and
0121: * setter methods. The tester and getter methods come in two
0122: * versions, one that is forwarded across wrapped types and one that
0123: * uses a boolean parameter to control forwarding.
0124: *
0125: * @author Robert Grimm
0126: * @version $Revision: 1.110 $
0127: */
0128: public abstract class Type extends Node {
0129:
0130: /**
0131: * A type's tag. Only leaves of the type hierarchy have their own
0132: * tags. A type's tag is accessed through {@link #tag()} and {@link
0133: * #wtag()}.
0134: */
0135: public static enum Tag {
0136: /** A boolean. */
0137: BOOLEAN,
0138: /** An array. */
0139: ARRAY,
0140: /** A class. */
0141: CLASS,
0142: /** An interface. */
0143: INTERFACE,
0144: /** A function. */
0145: FUNCTION,
0146: /** A method. */
0147: METHOD,
0148: /** A parameter. */
0149: PARAMETER,
0150: /** A wildcard. */
0151: WILDCARD,
0152: /** A pointer. */
0153: POINTER,
0154: /** A struct. */
0155: STRUCT,
0156: /** A tuple. */
0157: TUPLE,
0158: /** A union. */
0159: UNION,
0160: /** A variant. */
0161: VARIANT,
0162: /** An error. */
0163: ERROR,
0164: /** An internal type. */
0165: INTERNAL,
0166: /** A label. */
0167: LABEL,
0168: /** A float. */
0169: FLOAT,
0170: /** An integer. */
0171: INTEGER,
0172: /** A package. */
0173: PACKAGE,
0174: /** A unit type. */
0175: UNIT,
0176: /** A void type. */
0177: VOID,
0178: /** An alias. */
0179: ALIAS,
0180: /** An annotated type. */
0181: ANNOTATED,
0182: /** An enumerator. */
0183: ENUMERATOR,
0184: /** An enum. */
0185: ENUM,
0186: /** An instantiated type. */
0187: INSTANTIATED,
0188: /** A parameterized type. */
0189: PARAMETERIZED,
0190: /** A variable. */
0191: VARIABLE
0192: }
0193:
0194: // =========================================================================
0195:
0196: /** The flag for whether this type is sealed. */
0197: boolean sealed;
0198:
0199: // This type's location is implicit in the Node.
0200:
0201: /** This type's language. */
0202: Language language;
0203:
0204: /** This type's scope. */
0205: String scope;
0206:
0207: /** This type's constant value. */
0208: Constant constant;
0209:
0210: /** This type's shape. */
0211: Reference shape;
0212:
0213: /** This type's attributes. */
0214: List<Attribute> attributes;
0215:
0216: // =========================================================================
0217:
0218: /**
0219: * Create a new type. The newly created type does not have any
0220: * annotations and is not sealed.
0221: */
0222: public Type() { /* Nothing to do. */
0223: }
0224:
0225: /**
0226: * Create a new type. The newly created type is not sealed. Its
0227: * annotations are a copy of the specified template's annotations.
0228: *
0229: * @param template The type whose annotations to copy.
0230: */
0231: public Type(Type template) {
0232: if (null == template)
0233: return;
0234:
0235: setLocation(template);
0236: this .language = template.language;
0237: this .scope = template.scope;
0238: this .constant = template.constant;
0239: this .shape = template.shape;
0240: if (null != template.attributes) {
0241: this .attributes = new ArrayList<Attribute>(
0242: template.attributes);
0243: }
0244: }
0245:
0246: // =========================================================================
0247:
0248: /**
0249: * Create a deep copy of this type. The resulting type is not
0250: * sealed.
0251: *
0252: * @return A deep copy of this type.
0253: */
0254: public abstract Type copy();
0255:
0256: // =========================================================================
0257:
0258: /**
0259: * Determine whether this type is sealed.
0260: *
0261: * @return <code>true</code> if this type is sealed.
0262: */
0263: public boolean isSealed() {
0264: return sealed;
0265: }
0266:
0267: /**
0268: * Seal this type. Subclasses that reference other types must
0269: * override this method and, if the instance is not sealed, first
0270: * invoke the superclass' version and then seal all referenced
0271: * types. For example, if a subclass references a single type
0272: * <code>type</code>, the corresponding overridden method reads:
0273: * <pre>
0274: * public Type seal() {
0275: * if (! isSealed()) {
0276: * super.seal();
0277: * type.seal();
0278: * }
0279: * return this;
0280: * }
0281: * </pre>
0282: * First testing whether a type is sealed and then invoking the
0283: * superclass' <code>seal()</code> method avoids infinite recursions
0284: * for mutually recursive types.
0285: *
0286: * @see #seal(List)
0287: *
0288: * @return This type.
0289: */
0290: public Type seal() {
0291: sealed = true;
0292: return this ;
0293: }
0294:
0295: /**
0296: * Ensure that this type is not sealed. This method must be called
0297: * by any subclass before modifying its internal state.
0298: *
0299: * @throws IllegalStateException Signals that this type is sealed.
0300: */
0301: protected void checkNotSealed() {
0302: if (sealed) {
0303: throw new IllegalStateException("Type " + this
0304: + " is sealed");
0305: }
0306: }
0307:
0308: // =========================================================================
0309:
0310: /**
0311: * Annotate this type. If this type is not an annotated type or a
0312: * sealed annotated type, this method wraps this type in a new
0313: * {@link AnnotatedT}.
0314: *
0315: * @return The annotated type.
0316: */
0317: public Type annotate() {
0318: return isAnnotated() && (!isSealed()) ? this : new AnnotatedT(
0319: this );
0320: }
0321:
0322: /**
0323: * Deannotate this type. This method strips away any {@link
0324: * AnnotatedT} from this type.
0325: *
0326: * @return The deannotated type.
0327: */
0328: public Type deannotate() {
0329: Type t = this ;
0330: while (t.isAnnotated())
0331: t = t.toAnnotated().getType();
0332: return t;
0333: }
0334:
0335: // =========================================================================
0336:
0337: public Object setProperty(String name, Object value) {
0338: checkNotSealed();
0339: return super .setProperty(name, value);
0340: }
0341:
0342: public Object removeProperty(String name) {
0343: checkNotSealed();
0344: return super .removeProperty(name);
0345: }
0346:
0347: public Set<String> properties() {
0348: if (sealed) {
0349: return Collections.unmodifiableSet(super .properties());
0350: } else {
0351: return properties();
0352: }
0353: }
0354:
0355: // =========================================================================
0356:
0357: /**
0358: * Determine whether this type or any wrapped type has a location.
0359: * Calling this method on type <code>t</code> is equivalent to:
0360: * <pre>
0361: * t.hasLocation(true)
0362: * </pre>
0363: *
0364: * @see #hasLocation(boolean)
0365: *
0366: * @return <code>true</code> if this type or any wrapped type has a
0367: * location.
0368: */
0369: public boolean hasLocation() {
0370: return hasLocation(true);
0371: }
0372:
0373: /**
0374: * Determine whether this type or any wrapped type has a location.
0375: *
0376: * @param forward The flag for whether to forward this method across
0377: * wrapped types.
0378: * @return <code>true</code> if this type or any wrapped type has a
0379: * location.
0380: */
0381: public boolean hasLocation(boolean forward) {
0382: return super .hasLocation();
0383: }
0384:
0385: /**
0386: * Get this type's or any wrapped type's location. Calling this
0387: * method on type <code>t</code> is equivalent to:
0388: * <pre>
0389: * t.getLocation(true)
0390: * </pre>
0391: *
0392: * @see #getLocation(boolean)
0393: *
0394: * @return The location or <code>null</code> if this type or any
0395: * wrapped type does not have a location.
0396: */
0397: public Location getLocation() {
0398: return getLocation(true);
0399: }
0400:
0401: /**
0402: * Get this type's or any wrapped type's location.
0403: *
0404: * @param forward The flag for whether to forward this method across
0405: * wrapped types.
0406: * @return The location or <code>null</code> if this type or any
0407: * wrapped type does not have a location.
0408: */
0409: public Location getLocation(boolean forward) {
0410: return super .getLocation();
0411: }
0412:
0413: /**
0414: * Set this type's location.
0415: *
0416: * @param location The location.
0417: * @return This type.
0418: * @throws IllegalStateException Signals that this type is sealed.
0419: */
0420: public Type locate(Location location) {
0421: setLocation(location);
0422: return this ;
0423: }
0424:
0425: /**
0426: * Set this type's location.
0427: *
0428: * @param locatable The locatable.
0429: * @return This type.
0430: * @throws IllegalStateException Signals that this type is sealed.
0431: */
0432: public Type locate(Locatable locatable) {
0433: setLocation(locatable);
0434: return this ;
0435: }
0436:
0437: public void setLocation(Location location) {
0438: checkNotSealed();
0439: super .setLocation(location);
0440: }
0441:
0442: public void setLocation(Locatable locatable) {
0443: checkNotSealed();
0444: super .setLocation(locatable);
0445: }
0446:
0447: // =========================================================================
0448:
0449: /**
0450: * Determine whether this type or any wrapped type has a language.
0451: * Calling this method on type <code>t</code> is equivalent to:
0452: * <pre>
0453: * t.hasLanguage(true)
0454: * </pre>
0455: *
0456: * @see #hasLanguage(boolean)
0457: *
0458: * @return <code>true</code> if this type or any wrapped type has a
0459: * language.
0460: */
0461: public boolean hasLanguage() {
0462: return hasLanguage(true);
0463: }
0464:
0465: /**
0466: * Determine whether this type or any wrapped type has a language.
0467: *
0468: * @param forward The flag for whether to forward this method across
0469: * wrapped types.
0470: * @return <code>true</code> if this type or any wrapped type has a
0471: * language.
0472: */
0473: public boolean hasLanguage(boolean forward) {
0474: return null != language;
0475: }
0476:
0477: /**
0478: * Get this type's or any wrapped type's language. Calling this
0479: * method on type <code>t</code> is equivalent to:
0480: * <pre>
0481: * t.getLanguage(true)
0482: * </pre>
0483: *
0484: * @see #getLanguage(boolean)
0485: *
0486: * @return The language or <code>null</code> if this type or any
0487: * wrapped type does not have a language.
0488: */
0489: public Language getLanguage() {
0490: return getLanguage(true);
0491: }
0492:
0493: /**
0494: * Get this type's or any wrapped type's language.
0495: *
0496: * @param forward The flag for whether to forward this method across
0497: * wrapped types.
0498: * @return The language or <code>null</code> if this type or any
0499: * wrapped type does not have a language.
0500: */
0501: public Language getLanguage(boolean forward) {
0502: return language;
0503: }
0504:
0505: /**
0506: * Set this type's language.
0507: *
0508: * @param language The language.
0509: * @return This type.
0510: * @throws IllegalStateException Signals that this type is sealed.
0511: */
0512: public Type language(Language language) {
0513: checkNotSealed();
0514: this .language = language;
0515: return this ;
0516: }
0517:
0518: // =========================================================================
0519:
0520: /**
0521: * Determine whether this type or any wrapped type has a scope.
0522: * Calling this method on type <code>t</code> is equivalent to:
0523: * <pre>
0524: * t.hasScope(true)
0525: * </pre>
0526: *
0527: * @see #hasScope(boolean)
0528: *
0529: * @return <code>true</code> if this type or any wrapped type has a
0530: * scope.
0531: */
0532: public boolean hasScope() {
0533: return hasScope(true);
0534: }
0535:
0536: /**
0537: * Determine whether this type or any wrapped type has a scope.
0538: *
0539: * @param forward The flag for whether to forward this method across
0540: * wrapped types.
0541: * @return <code>true</code> if this type or any wrapped type has a
0542: * scope.
0543: */
0544: public boolean hasScope(boolean forward) {
0545: return null != scope;
0546: }
0547:
0548: /**
0549: * Get this type's or any wrapped type's scope. Calling this method
0550: * on type <code>t</code> is equivalent to:
0551: * <pre>
0552: * t.getScope(true)
0553: * </pre>
0554: *
0555: * @see #getScope(boolean)
0556: *
0557: * @return The scope or <code>null</code> if this type or any
0558: * wrapped type does not have a scope.
0559: */
0560: public String getScope() {
0561: return getScope(true);
0562: }
0563:
0564: /**
0565: * Get this type's or any wrapped type's scope.
0566: *
0567: * @param forward The flag for whether to forward this method across
0568: * wrapped types.
0569: * @return The scope or <code>null</code> if this type or any
0570: * wrapped type does not have a scope.
0571: */
0572: public String getScope(boolean forward) {
0573: return scope;
0574: }
0575:
0576: /**
0577: * Set this type's scope.
0578: *
0579: * @param scope The scope.
0580: * @return This type.
0581: * @throws IllegalStateException Signals that this type is sealed.
0582: */
0583: public Type scope(String scope) {
0584: checkNotSealed();
0585: this .scope = scope;
0586: return this ;
0587: }
0588:
0589: // =========================================================================
0590:
0591: /**
0592: * Determine whether this type or any wrapped type has a constant.
0593: * Calling this method on type <code>t</code> is equivalent to:
0594: * <pre>
0595: * t.hasConstant(true)
0596: * </pre>
0597: *
0598: * @see #hasConstant(boolean)
0599: *
0600: * @return <code>true</code> if this type has a constant.
0601: */
0602: public boolean hasConstant() {
0603: return hasConstant(true);
0604: }
0605:
0606: /**
0607: * Determine whether this type or any wrapped type has a constant.
0608: *
0609: * @param forward The flag for whether to forward this method across
0610: * wrapped types.
0611: * @return <code>true</code> if this type or any wrapped type has a
0612: * constant.
0613: */
0614: public boolean hasConstant(boolean forward) {
0615: return null != constant;
0616: }
0617:
0618: /**
0619: * Get this type's or any wrapped type's constant. Calling this
0620: * method on type <code>t</code> is equivalent to:
0621: * <pre>
0622: * t.getConstant(true)
0623: * </pre>
0624: *
0625: * @see #getConstant(boolean)
0626: *
0627: * @return The constant or <code>null</code> if this type or any
0628: * wrapped type does not have a constant.
0629: */
0630: public Constant getConstant() {
0631: return getConstant(true);
0632: }
0633:
0634: /**
0635: * Get this type's or any wrapped type's constant.
0636: *
0637: * @param forward The flag for whether to forward this method across
0638: * wrapped types.
0639: * @return The constant or <code>null</code> if this type or any
0640: * wrapped type does not have a constant.
0641: */
0642: public Constant getConstant(boolean forward) {
0643: return constant;
0644: }
0645:
0646: /**
0647: * Set this type's constant.
0648: *
0649: * @see #constant(Object)
0650: *
0651: * @param value The value.
0652: * @return This type.
0653: * @throws IllegalStateException Signals that this type is sealed.
0654: */
0655: public Type constant(boolean value) {
0656: return constant(value ? BigInteger.ONE : BigInteger.ZERO);
0657: }
0658:
0659: /**
0660: * Set this type's constant.
0661: *
0662: * @param value The value.
0663: * @return This type.
0664: * @throws IllegalArgumentException Signals an invalid value.
0665: * @throws IllegalStateException Signals that this type is sealed.
0666: */
0667: public Type constant(Object value) {
0668: checkNotSealed();
0669: this .constant = new Constant(value);
0670: return this ;
0671: }
0672:
0673: // =========================================================================
0674:
0675: /**
0676: * Determine whether this type or any wrapped type has a shape.
0677: * Calling this method on type <code>t</code> is equivalent to:
0678: * <pre>
0679: * t.hasShape(true)
0680: * </pre>
0681: *
0682: * @see #hasShape(boolean)
0683: *
0684: * @return <code>true</code> if this type or any wrapped type has a
0685: * shape.
0686: */
0687: public boolean hasShape() {
0688: return hasShape(true);
0689: }
0690:
0691: /**
0692: * Determine whether this type or any wrapped type has a shape.
0693: *
0694: * @param forward The flag for whether to forward this method across
0695: * wrapped types.
0696: * @return <code>true</code> if this type or any wrapped type has a
0697: * shape.
0698: */
0699: public boolean hasShape(boolean forward) {
0700: return null != shape;
0701: }
0702:
0703: /**
0704: * Get this type's or any wrapped type's shape. Calling this method
0705: * on type <code>t</code> is equivalent to:
0706: * <pre>
0707: * t.getShape(true)
0708: * </pre>
0709: *
0710: * @see #getShape(boolean)
0711: *
0712: * @return The shape or <code>null</code> if this type or any
0713: * wrapped type does not have a shape.
0714: */
0715: public Reference getShape() {
0716: return getShape(true);
0717: }
0718:
0719: /**
0720: * Get this type's or any wrapped type's shape.
0721: *
0722: * @param forward The flag for whether to forward this method across
0723: * wrapped types.
0724: * @return The shape or <code>null</code> if this type or any
0725: * wrapped type does not have a shape.
0726: */
0727: public Reference getShape(boolean forward) {
0728: return shape;
0729: }
0730:
0731: /**
0732: * Set this type's shape to a variable reference with the specified
0733: * name.
0734: *
0735: * @see StaticReference
0736: * @see DynamicReference
0737: * @see #shape(Reference)
0738: *
0739: * @param isStatic The flag for whether the variable is static.
0740: * @param name The variable name.
0741: * @return This type.
0742: * @throws IllegalStateException Signals that this type is sealed.
0743: */
0744: public Type shape(boolean isStatic, String name) {
0745: if (isStatic) {
0746: return shape(new StaticReference(name, resolve()));
0747: } else {
0748: return shape(new DynamicReference(name, resolve()));
0749: }
0750: }
0751:
0752: /**
0753: * Set this type's shape.
0754: *
0755: * @param shape The shape represented as a reference.
0756: * @return This type.
0757: * @throws IllegalStateException Signals that this type is sealed.
0758: */
0759: public Type shape(Reference shape) {
0760: checkNotSealed();
0761: this .shape = shape;
0762: return this ;
0763: }
0764:
0765: // =========================================================================
0766:
0767: /**
0768: * Determine whether this type has any attributes. Note that this
0769: * method does <em>not</em> check any wrapped types.
0770: *
0771: * @return <code>true</code> if this type has any attributes.
0772: */
0773: public boolean hasAttributes() {
0774: return ((null != attributes) && (!attributes.isEmpty()));
0775: }
0776:
0777: /**
0778: * Get this type's attributes.
0779: *
0780: * @return This type's attributes.
0781: */
0782: public List<Attribute> attributes() {
0783: if (null == attributes) {
0784: return Collections.emptyList();
0785: } else if (sealed) {
0786: return Collections.unmodifiableList(attributes);
0787: } else {
0788: return attributes;
0789: }
0790: }
0791:
0792: // =========================================================================
0793:
0794: /**
0795: * Determine whether this type or any wrapped type has the specified
0796: * attribute. Calling this method on type <code>t</code> is
0797: * equivalent to:
0798: * <pre>
0799: * t.hasAttribute(att, true)
0800: * </pre>
0801: *
0802: * @see #hasAttribute(Attribute,boolean)
0803: *
0804: * @param att The attribute.
0805: * @return <code>true</code> if this type or any wrapped type has
0806: * the attribute.
0807: */
0808: public boolean hasAttribute(Attribute att) {
0809: return hasAttribute(att, true);
0810: }
0811:
0812: /**
0813: * Determine whether this type or any wrapped type has the specified
0814: * attribute.
0815: *
0816: * @param att The attribute.
0817: * @param forward The flag for whether to forward this method across
0818: * wrapped types.
0819: * @return <code>true</code> if this type or any wrapped type has
0820: * the attribute.
0821: */
0822: public boolean hasAttribute(Attribute att, boolean forward) {
0823: return ((null != attributes) && attributes.contains(att));
0824: }
0825:
0826: /**
0827: * Determine whether this type has an attribute with the specified
0828: * name. Calling this method on type <code>t</code> is equivalent
0829: * to:
0830: * <pre>
0831: * null != t.getAttribute(name, true)
0832: * </pre>
0833: *
0834: * @see #getAttribute(String,boolean)
0835: *
0836: * @param name The name.
0837: * @return <code>true</code> if this type or any wrapped type has
0838: * an attribute with the specified name.
0839: */
0840: public boolean hasAttribute(String name) {
0841: return null != getAttribute(name);
0842: }
0843:
0844: /**
0845: * Determine whether this type has an attribute with the specified
0846: * name. Calling this method on type <code>t</code> is equivalent
0847: * to:
0848: * <pre>
0849: * null != t.getAttribute(name, forward)
0850: * </pre>
0851: *
0852: * @link #getAttribute(String,boolean)
0853: *
0854: * @param name The name.
0855: * @param forward The flag for whether to forward this method across
0856: * wrapped types.
0857: * @return <code>true</code> if this type or any wrapped type has
0858: * an attribute with the specified name.
0859: */
0860: public boolean hasAttribute(String name, boolean forward) {
0861: return null != getAttribute(name, forward);
0862: }
0863:
0864: /**
0865: * Get the attribute with the specified name. Calling this method
0866: * on type <code>t</code> is equivalent to:
0867: * <pre>
0868: * t.getAttribute(name, true)
0869: * </pre>
0870: *
0871: * @see #getAttribute(String,boolean)
0872: *
0873: * @param name The name.
0874: * @return An attribute with that name or <code>null</code> if this
0875: * type or any wrapped type does not have such an attribute.
0876: */
0877: public Attribute getAttribute(String name) {
0878: return getAttribute(name, true);
0879: }
0880:
0881: /**
0882: * Get the attribute with the specified name.
0883: *
0884: * @param name The name.
0885: * @param forward The flag for whether to forward this method across
0886: * wrapped types.
0887: * @return An attribute with the name or <code>null</code> if this
0888: * or any wrapped type does not have such an attribute.
0889: */
0890: public Attribute getAttribute(String name, boolean forward) {
0891: return Attribute.get(name, attributes);
0892: }
0893:
0894: // =========================================================================
0895:
0896: /**
0897: * Add the specified attribute. This method adds the specified
0898: * attribute to this type's list of attributes — without
0899: * checking whether the type already has that attribute. For almost
0900: * all applications of attributes, it is preferable to use {@link
0901: * #attribute(Attribute)}, {@link #attribute(List)}, or {@link
0902: * #attribute(Type)}.
0903: *
0904: * @param att The new attribute.
0905: * @throws IllegalStateException Signals that this type is sealed.
0906: */
0907: public void addAttribute(Attribute att) {
0908: checkNotSealed();
0909: if (null == attributes)
0910: attributes = new ArrayList<Attribute>();
0911: attributes.add(att);
0912: }
0913:
0914: /**
0915: * Remove the specified attribute. Note that this method does
0916: * <em>not</em> remove the attribute from any wrapped types.
0917: *
0918: * @param att The attribute.
0919: * @return <code>true</code> if this type had the specified
0920: * attribute.
0921: * @throws IllegalStateException Signals that this type is sealed.
0922: */
0923: public boolean removeAttribute(Attribute att) {
0924: checkNotSealed();
0925: return null != attributes ? attributes.remove(att) : false;
0926: }
0927:
0928: // =========================================================================
0929:
0930: /**
0931: * Annotate this type with the specified attribute. If this type or
0932: * any wrapped type does not have the specified attribute, this
0933: * method adds the attribute to this type's list of attributes.
0934: *
0935: * @param att The attribute.
0936: * @return This type.
0937: * @throws IllegalStateException Signals that this type is sealed.
0938: */
0939: public Type attribute(Attribute att) {
0940: if (!hasAttribute(att)) {
0941: addAttribute(att);
0942: }
0943: return this ;
0944: }
0945:
0946: /**
0947: * Annotate this type with the specified attributes.
0948: *
0949: * @see #attribute(Attribute)
0950: *
0951: * @param attributes The attributes.
0952: * @return This type.
0953: * @throws IllegalStateException Signals that this type is sealed.
0954: */
0955: public Type attribute(List<Attribute> attributes) {
0956: for (Attribute att : attributes) {
0957: if (!hasAttribute(att))
0958: addAttribute(att);
0959: }
0960: return this ;
0961: }
0962:
0963: /**
0964: * Annotate this type with the specified type's attributes.
0965: *
0966: * @param template The type whose annotations to copy.
0967: * @return This type.
0968: * @throws IllegalStateException Signals that this type is sealed.
0969: */
0970: public Type attribute(Type template) {
0971: do {
0972: // If the template has any attributes, copy them.
0973: if (template.hasAttributes()) {
0974: for (Attribute att : template.attributes()) {
0975: if (!hasAttribute(att))
0976: addAttribute(att);
0977: }
0978: }
0979:
0980: // If the template is a wrapped type, continue with the wrapped type.
0981: template = template.isWrapped() ? template.toWrapped()
0982: .getType() : null;
0983: } while (null != template);
0984:
0985: // Done.
0986: return this ;
0987: }
0988:
0989: // =========================================================================
0990:
0991: /**
0992: * Mark the specified node as having this type. This method sets
0993: * the node's {@link Constants#TYPE type property} to this type.
0994: *
0995: * @param node The node.
0996: * @throws IllegalArgumentException Signals that the node already
0997: * has a type property.
0998: */
0999: public void mark(Node node) {
1000: if (node.hasProperty(Constants.TYPE)) {
1001: throw new IllegalArgumentException("Node " + node
1002: + " already has type");
1003: } else {
1004: node.setProperty(Constants.TYPE, this );
1005: }
1006: }
1007:
1008: // =========================================================================
1009:
1010: /**
1011: * Determine whether this type has the specified tag. Invocations
1012: * to this method are forwarded across wrapped types. Calling this
1013: * method on type <code>t</code> is equivalent to:
1014: * <pre>
1015: * tag == t.tag()
1016: * </pre>
1017: *
1018: * @see #tag()
1019: *
1020: * @param tag The tag.
1021: * @return <code>true</code> if this type has the specified tag.
1022: */
1023: public boolean hasTag(Tag tag) {
1024: return tag == tag();
1025: }
1026:
1027: /**
1028: * Get this type's tag. Invocations to this method are forwarded
1029: * across wrapped types.
1030: *
1031: * @see #wtag()
1032: *
1033: * @return This type's tag.
1034: */
1035: public abstract Tag tag();
1036:
1037: /**
1038: * Determine whether this wrapped type has the specified tag.
1039: * Invocations to this method are <em>not</em> forwarded across
1040: * wrapped types. Calling this method on type <code>t</code> is
1041: * equivalent to:
1042: * <pre>
1043: * tag == wtag()
1044: * </pre>
1045: *
1046: * @see #wtag()
1047: *
1048: * @param tag The tag.
1049: * @return <code>true</code> if this wrapped type has the specified
1050: * tag.
1051: */
1052: public boolean hasWTag(Tag tag) {
1053: return tag == wtag();
1054: }
1055:
1056: /**
1057: * Get this wrapped type's tag. Invocations to this method are
1058: * <em>not</em> forwarded across wrapped types.
1059: *
1060: * @see #tag()
1061: *
1062: * @return This wrapped type's tag.
1063: */
1064: public Tag wtag() {
1065: return tag();
1066: }
1067:
1068: // =========================================================================
1069:
1070: /**
1071: * Determine whether this type is an error.
1072: *
1073: * @link #hasError()
1074: *
1075: * @return <code>true</code> if this type is internal.
1076: */
1077: public boolean isError() {
1078: return false;
1079: }
1080:
1081: /**
1082: * Determine whether this type has an error. This method identifies
1083: * the {@link ErrorT error type} even if it is wrapped. Calling this
1084: * method on type <code>t</code> is equivalent to:
1085: * <pre>
1086: * Type.Tag.Error == tag()
1087: * </pre>
1088: *
1089: * @see #tag()
1090: *
1091: * @return <code>true</code> if this type has an error.
1092: */
1093: public boolean hasError() {
1094: return Tag.ERROR == tag();
1095: }
1096:
1097: // =========================================================================
1098:
1099: /**
1100: * Determine whether this type is a type parameter.
1101: *
1102: * @return <code>true</code> if this type is a parameter.
1103: */
1104: public boolean isParameter() {
1105: return false;
1106: }
1107:
1108: /**
1109: * Get this type as a type parameter.
1110: *
1111: * @return This type as a parameter.
1112: * @throws ClassCastException Signals that this type is not a
1113: * parameter.
1114: */
1115: public Parameter toParameter() {
1116: throw new ClassCastException("Not a parameter " + this );
1117: }
1118:
1119: /**
1120: * Determine whether this type is a wildcard.
1121: *
1122: * @return <code>true</code> if this type is a wildcard.
1123: */
1124: public boolean isWildcard() {
1125: return false;
1126: }
1127:
1128: /**
1129: * Get this type as a wildcard.
1130: *
1131: * @return This type as a wildcard.
1132: * @throws ClassCastException Signals that this type is not a
1133: * wildcard.
1134: */
1135: public Wildcard toWildcard() {
1136: throw new ClassCastException("Not a wildcard " + this );
1137: }
1138:
1139: /**
1140: * Determine whether this type is void.
1141: *
1142: * @return <code>true</code> if this type is void.
1143: */
1144: public boolean isVoid() {
1145: return false;
1146: }
1147:
1148: /**
1149: * Get this type as a void type.
1150: *
1151: * @return This type as a void type.
1152: * @throws ClassCastException Signals that this type is not a void
1153: * type.
1154: */
1155: public VoidT toVoid() {
1156: throw new ClassCastException("Not a void " + this );
1157: }
1158:
1159: /**
1160: * Determine whether this type is the unit type.
1161: *
1162: * @return <code>true</code> if this type is the unit type.
1163: */
1164: public boolean isUnit() {
1165: return false;
1166: }
1167:
1168: /**
1169: * Get this type as a unit type.
1170: *
1171: * @return This type as a unit type.
1172: * @throws ClassCastException Signals that this type is not a unit
1173: * type.
1174: */
1175: public UnitT toUnit() {
1176: throw new ClassCastException("Not a unit " + this );
1177: }
1178:
1179: /**
1180: * Determine whether this type is a boolean.
1181: *
1182: * @return <code>true</code> if this type is a boolean.
1183: */
1184: public boolean isBoolean() {
1185: return false;
1186: }
1187:
1188: /**
1189: * Get this type as a boolean.
1190: *
1191: * @return This type as a boolean.
1192: * @throws ClassCastException Signals that this type is a not a
1193: * boolean.
1194: */
1195: public BooleanT toBoolean() {
1196: throw new ClassCastException("Not a boolean " + this );
1197: }
1198:
1199: /**
1200: * Determine whether this type is a number.
1201: *
1202: * @return <code>true</code> if this type is a number.
1203: */
1204: public boolean isNumber() {
1205: return false;
1206: }
1207:
1208: /**
1209: * Get this type as a number.
1210: *
1211: * @return This type as a number.
1212: * @throws ClassCastException Signals that this type is not a
1213: * number.
1214: */
1215: public NumberT toNumber() {
1216: throw new ClassCastException("Not a number " + this );
1217: }
1218:
1219: /**
1220: * Determine whether this type is an integer.
1221: *
1222: * @return <code>true</code> if this type is an integer.
1223: */
1224: public boolean isInteger() {
1225: return false;
1226: }
1227:
1228: /**
1229: * Get this type as an integer.
1230: *
1231: * @return This type as an integer.
1232: * @throws ClassCastException Signals that this type is not an
1233: * integer.
1234: */
1235: public IntegerT toInteger() {
1236: throw new ClassCastException("Not an integer " + this );
1237: }
1238:
1239: /**
1240: * Determine whether this type is a float.
1241: *
1242: * @return <code>true</code> if this type is a float.
1243: */
1244: public boolean isFloat() {
1245: return false;
1246: }
1247:
1248: /**
1249: * Get this type as a float.
1250: *
1251: * @return This type as a float.
1252: * @throws ClassCastException Signals that this type is not a
1253: * float.
1254: */
1255: public FloatT toFloat() {
1256: throw new ClassCastException("Not a float " + this );
1257: }
1258:
1259: /**
1260: * Determine whether this type is internal.
1261: *
1262: * @return <code>true</code> if this type is internal.
1263: */
1264: public boolean isInternal() {
1265: return false;
1266: }
1267:
1268: /**
1269: * Get this type as an internal type.
1270: *
1271: * @return This type as an internal type.
1272: * @throws ClassCastException Signals that this type is not an
1273: * internal type.
1274: */
1275: public InternalT toInternal() {
1276: throw new ClassCastException("Not an internal type " + this );
1277: }
1278:
1279: /**
1280: * Determine whether this type is a label.
1281: *
1282: * @return <code>true</code> if this type is a label.
1283: */
1284: public boolean isLabel() {
1285: return false;
1286: }
1287:
1288: /**
1289: * Get this type as a label.
1290: *
1291: * @return This type as a label.
1292: * @throws ClassCastException Signals that this type is not a
1293: * label.
1294: */
1295: public LabelT toLabel() {
1296: throw new ClassCastException("Not a label " + this );
1297: }
1298:
1299: /**
1300: * Determine whether this type is a package.
1301: *
1302: * @return <code>true</code> if this type is a package.
1303: */
1304: public boolean isPackage() {
1305: return false;
1306: }
1307:
1308: /**
1309: * Get this type as a package.
1310: *
1311: * @return This type as a package.
1312: * @throws ClassCastException Signals that this type is not a
1313: * package.
1314: */
1315: public PackageT toPackage() {
1316: throw new ClassCastException("Not a package " + this );
1317: }
1318:
1319: /**
1320: * Determine whether this type is derived.
1321: *
1322: * @return <code>true</code> if this type is derived.
1323: */
1324: public boolean isDerived() {
1325: return false;
1326: }
1327:
1328: /**
1329: * Determine whether this type is a pointer.
1330: *
1331: * @return <code>true</code> if this type is a pointer.
1332: */
1333: public boolean isPointer() {
1334: return false;
1335: }
1336:
1337: /**
1338: * Get this type as a pointer.
1339: *
1340: * @return This type as a pointer.
1341: * @throws ClassCastException Signals that this type is not a
1342: * pointer.
1343: */
1344: public PointerT toPointer() {
1345: throw new ClassCastException("Not a pointer " + this );
1346: }
1347:
1348: /**
1349: * Determine whether this type is an array.
1350: *
1351: * @return <code>true</code> if this type is an array.
1352: */
1353: public boolean isArray() {
1354: return false;
1355: }
1356:
1357: /**
1358: * Get this type as an array.
1359: *
1360: * @return This type as an array.
1361: * @throws ClassCastException Signals that this type is not an
1362: * array.
1363: */
1364: public ArrayT toArray() {
1365: throw new ClassCastException("Not an array " + this );
1366: }
1367:
1368: /**
1369: * Determine whether this type contains a struct or union.
1370: *
1371: * @return <code>true</code> if this type contains a struct or
1372: * union.
1373: */
1374: public boolean hasStructOrUnion() {
1375: switch (tag()) {
1376: case STRUCT:
1377: case UNION:
1378: return true;
1379: default:
1380: return false;
1381: }
1382: }
1383:
1384: /**
1385: * Determine whether this type is a struct.
1386: *
1387: * @return <code>true</code> if this type is a struct.
1388: */
1389: public boolean isStruct() {
1390: return false;
1391: }
1392:
1393: /**
1394: * Get this type as a struct.
1395: *
1396: * @return This type as a struct.
1397: * @throws ClassCastException Signas that this type is not a
1398: * struct.
1399: */
1400: public StructT toStruct() {
1401: throw new ClassCastException("Not a struct " + this );
1402: }
1403:
1404: /**
1405: * Determine whether this type is a union.
1406: *
1407: * @return <code>true</code> if this type is a union.
1408: */
1409: public boolean isUnion() {
1410: return false;
1411: }
1412:
1413: /**
1414: * Get this type as a union.
1415: *
1416: * @return This type as a union.
1417: * @throws ClassCastException Signals that this type is not a
1418: * union.
1419: */
1420: public UnionT toUnion() {
1421: throw new ClassCastException("Not a union " + this );
1422: }
1423:
1424: /**
1425: * Determine whether this type is a function.
1426: *
1427: * @return <code>true</code> if this type is a function.
1428: */
1429: public boolean isFunction() {
1430: return false;
1431: }
1432:
1433: /**
1434: * Get this type as a function.
1435: *
1436: * @return This type has a function.
1437: * @throws ClassCastException Signals that this type is not a
1438: * function.
1439: */
1440: public FunctionT toFunction() {
1441: throw new ClassCastException("Not a function " + this );
1442: }
1443:
1444: /**
1445: * Determine whether this type is a method.
1446: *
1447: * @return <code>true</code> if this type is a method.
1448: */
1449: public boolean isMethod() {
1450: return false;
1451: }
1452:
1453: /**
1454: * Get this type as a method.
1455: *
1456: * @return This type as a method.
1457: * @throws ClassCastException Signals that this type is not a
1458: * method.
1459: */
1460: public MethodT toMethod() {
1461: throw new ClassCastException("Not a method " + this );
1462: }
1463:
1464: /**
1465: * Determine whether this type is a class.
1466: *
1467: * @return <code>true</code> if this type is a class.
1468: */
1469: public boolean isClass() {
1470: return false;
1471: }
1472:
1473: /**
1474: * Get this type as a class.
1475: *
1476: * @return This type as a class.
1477: * @throws ClassCastException Signals that this type is not a class.
1478: */
1479: public ClassT toClass() {
1480: throw new ClassCastException("Not a class " + this );
1481: }
1482:
1483: /**
1484: * Determine whether this type is an interface.
1485: *
1486: * @return <code>true</code> if this type is an interface.
1487: */
1488: public boolean isInterface() {
1489: return false;
1490: }
1491:
1492: /**
1493: * Get this type as an interface.
1494: *
1495: * @return This type as an interface.
1496: * @throws ClassCastException Signals that this type is not an
1497: * interface.
1498: */
1499: public InterfaceT toInterface() {
1500: throw new ClassCastException("Not an interface " + this );
1501: }
1502:
1503: /**
1504: * Determine whether this type is an tuple.
1505: *
1506: * @return <code>true</code> if this type is an tuple.
1507: */
1508: public boolean isTuple() {
1509: return false;
1510: }
1511:
1512: /**
1513: * Get this type as an tuple.
1514: *
1515: * @return This type as an tuple.
1516: * @throws ClassCastException Signals that this type is not an tuple.
1517: */
1518: public TupleT toTuple() {
1519: throw new ClassCastException("Not an tuple " + this );
1520: }
1521:
1522: /**
1523: * Determine whether this type is an variant.
1524: *
1525: * @return <code>true</code> if this type is an variant.
1526: */
1527: public boolean isVariant() {
1528: return false;
1529: }
1530:
1531: /**
1532: * Get this type as an variant.
1533: *
1534: * @return This type as an variant.
1535: * @throws ClassCastException Signals that this type is not an variant.
1536: */
1537: public VariantT toVariant() {
1538: throw new ClassCastException("Not an variant " + this );
1539: }
1540:
1541: // =========================================================================
1542:
1543: /**
1544: * Determine whether this type is wrapped.
1545: *
1546: * @return <code>true</code> if this type is wrapped.
1547: */
1548: public boolean isWrapped() {
1549: return false;
1550: }
1551:
1552: /**
1553: * Get this type as a wrapped type.
1554: *
1555: * @return This type as a wrapped type.
1556: * @throws ClassCastException Signals that this type is not wrapped.
1557: */
1558: public WrappedT toWrapped() {
1559: throw new ClassCastException("Not a wrapped type " + this );
1560: }
1561:
1562: // =========================================================================
1563:
1564: /**
1565: * Determine whether this type is annotated.
1566: *
1567: * @return <code>true</code> if this type is annotated.
1568: */
1569: public boolean isAnnotated() {
1570: return false;
1571: }
1572:
1573: /**
1574: * Determine whether this type has an annotated type.
1575: *
1576: * @return <code>true</code> if this type has an annotated type.
1577: */
1578: public boolean hasAnnotated() {
1579: return false;
1580: }
1581:
1582: /**
1583: * Get this type as an annotated type.
1584: *
1585: * @return This type as an annotated type.
1586: * @throws ClassCastException Signas that this type is not an
1587: * annotated type.
1588: */
1589: public AnnotatedT toAnnotated() {
1590: throw new ClassCastException("Not an annotated type " + this );
1591: }
1592:
1593: /**
1594: * Determine whether this type is an alias.
1595: *
1596: * @return <code>true</code> if this type is an alias.
1597: */
1598: public boolean isAlias() {
1599: return false;
1600: }
1601:
1602: /**
1603: * Determine whether this type contains an alias.
1604: *
1605: * @return <code>true</code> if this type contains an alias.
1606: */
1607: public boolean hasAlias() {
1608: return false;
1609: }
1610:
1611: /**
1612: * Get this type as an alias.
1613: *
1614: * @return This type as an alias.
1615: * @throws ClassCastException Signals that this type is not an
1616: * alias.
1617: */
1618: public AliasT toAlias() {
1619: throw new ClassCastException("Not an alias " + this );
1620: }
1621:
1622: /**
1623: * Determine whether this type is an enum.
1624: *
1625: * @return <code>true</code> if this type is an enum.
1626: */
1627: public boolean isEnum() {
1628: return false;
1629: }
1630:
1631: /**
1632: * Determine whether this type contains an enum.
1633: *
1634: * @return <code>true</code> if this type contains an enum.
1635: */
1636: public boolean hasEnum() {
1637: return false;
1638: }
1639:
1640: /**
1641: * Get this type as an enum.
1642: *
1643: * @return This type as an enum.
1644: * @throws ClassCastException Signals that this type is not an enum.
1645: */
1646: public EnumT toEnum() {
1647: throw new ClassCastException("Not an enum " + this );
1648: }
1649:
1650: /**
1651: * Determine whether this type is an enumerator.
1652: *
1653: * @return <code>true</code> if this type is an enumerator.
1654: */
1655: public boolean isEnumerator() {
1656: return false;
1657: }
1658:
1659: /**
1660: * Determine whether this type contains an enumerator.
1661: *
1662: * @return <code>true</code> if this type contains an enumerator.
1663: */
1664: public boolean hasEnumerator() {
1665: return false;
1666: }
1667:
1668: /**
1669: * Get this type as an enumerator.
1670: *
1671: * @return This type as an enumerator.
1672: * @throws ClassCastException Signals that this type is not an
1673: * enumerator.
1674: */
1675: public EnumeratorT toEnumerator() {
1676: throw new ClassCastException("Not an enumerator " + this );
1677: }
1678:
1679: /**
1680: * Determine whether this type is instantiated.
1681: *
1682: * @return <code>true</code> if this type is instantiated.
1683: */
1684: public boolean isInstantiated() {
1685: return false;
1686: }
1687:
1688: /**
1689: * Determine whether this type has an instantiated type.
1690: *
1691: * @return <code>true</code> if this type has an instantiated type.
1692: */
1693: public boolean hasInstantiated() {
1694: return false;
1695: }
1696:
1697: /**
1698: * Get this type as an instantiated type.
1699: *
1700: * @return This type as an instantiated type.
1701: * @throws ClassCastException Signas that this type is not an
1702: * instantiated type.
1703: */
1704: public InstantiatedT toInstantiated() {
1705: throw new ClassCastException("Not an instantiated type " + this );
1706: }
1707:
1708: /**
1709: * Determine whether this type is parameterized.
1710: *
1711: * @return <code>true</code> if this type is parameterized.
1712: */
1713: public boolean isParameterized() {
1714: return false;
1715: }
1716:
1717: /**
1718: * Determine whether this type has a parameterized type.
1719: *
1720: * @return <code>true</code> if this type has a parameterized type.
1721: */
1722: public boolean hasParameterized() {
1723: return false;
1724: }
1725:
1726: /**
1727: * Get this type as a parameterized type.
1728: *
1729: * @return This type as a parameterized type.
1730: * @throws ClassCastException Signas that this type is not a
1731: * parameterized type.
1732: */
1733: public ParameterizedT toParameterized() {
1734: throw new ClassCastException("Not a parameterized type " + this );
1735: }
1736:
1737: /**
1738: * Determine whether this type is a variable.
1739: *
1740: * @return <code>true</code> if this type is a variable.
1741: */
1742: public boolean isVariable() {
1743: return false;
1744: }
1745:
1746: /**
1747: * Determine whether this type contains a variable.
1748: *
1749: * @return <code>true</code> if this type contains a variable.
1750: */
1751: public boolean hasVariable() {
1752: return false;
1753: }
1754:
1755: /**
1756: * Get this type as a variable.
1757: *
1758: * @return This type as a variable.
1759: * @throws ClassCastException Signals that this type does not
1760: * contain a variable.
1761: */
1762: public VariableT toVariable() {
1763: throw new ClassCastException("Not a variable " + this );
1764: }
1765:
1766: // =========================================================================
1767:
1768: /**
1769: * Determine whether this type is tagged.
1770: *
1771: * @return <code>true</code> if this type is tagged.
1772: */
1773: public boolean hasTagged() {
1774: return false;
1775: }
1776:
1777: /**
1778: * Get this type as a tagged type.
1779: *
1780: * @see #hasTagged()
1781: *
1782: * @return This type as a tagged type.
1783: * @throws ClassCastException Signals that this type is not
1784: * tagged.
1785: */
1786: public Tagged toTagged() {
1787: throw new ClassCastException("Not a tagged type " + this );
1788: }
1789:
1790: // =========================================================================
1791:
1792: /**
1793: * Determine whether this type is concrete. This method returns
1794: * <code>true</code> if this type is not parameterized or is both
1795: * parameterized and instantiated.
1796: *
1797: * @return <code>true</code> if this type is concrete.
1798: */
1799: public boolean isConcrete() {
1800: return (!hasParameterized()) || hasInstantiated();
1801: }
1802:
1803: // =========================================================================
1804:
1805: /**
1806: * Resolve this type. This method removes any symbolic information,
1807: * i.e., wrapped types, and returns the underlying, "raw" type.
1808: *
1809: * @return The resolved type.
1810: */
1811: public Type resolve() {
1812: return this ;
1813: }
1814:
1815: // =========================================================================
1816:
1817: /**
1818: * Trace this type to the runtime's console. This method prints
1819: * this type to the runtime's console using a new instance of {@link
1820: * TypePrinter}; it is useful for debugging.
1821: *
1822: * @param runtime The runtime.
1823: */
1824: public void trace(Runtime runtime) {
1825: // Save the registered visitor.
1826: Visitor visitor = runtime.console().visitor();
1827: TypePrinter printer = new TypePrinter(runtime.console());
1828: try {
1829: printer.dispatch(this );
1830: runtime.console().pln();
1831: } finally {
1832: // Restore the previously registered visitor.
1833: runtime.console().register(visitor);
1834: }
1835: runtime.console().flush();
1836: }
1837:
1838: // =========================================================================
1839:
1840: /**
1841: * Cast the specified object to a type.
1842: *
1843: * @param type The type as an object.
1844: * @return The type as a type.
1845: * @throws ClassCastException Signals that the specified object is
1846: * not a type.
1847: */
1848: public static Type cast(Object type) {
1849: return (Type) type;
1850: }
1851:
1852: /**
1853: * Resolve the specified object as type.
1854: *
1855: * @param type The type.
1856: * @return The resolved type.
1857: * @throws ClassCastException Signals that the specified object is
1858: * not a type.
1859: */
1860: public static Type resolve(Object type) {
1861: return ((Type) type).resolve();
1862: }
1863:
1864: // =========================================================================
1865:
1866: /**
1867: * Copy the specified list of types. A null list is ignored.
1868: *
1869: * @param types The list of types.
1870: * @return A new list of the types' copies.
1871: */
1872: @SuppressWarnings("unchecked")
1873: public static <T extends Type> List<T> copy(List<T> types) {
1874: if (null == types)
1875: return null;
1876:
1877: List<T> copy = new ArrayList<T>(types.size());
1878: for (T t : types) {
1879: // This cast can never fail in the presence of covariant return
1880: // types for copy().
1881: copy.add((T) t.copy());
1882: }
1883: return copy;
1884: }
1885:
1886: /**
1887: * Seal the specified list of types. A null list is ignored.
1888: *
1889: * @param types The list of types.
1890: * @return An unmodifiable list of sealed types.
1891: */
1892: public static <T extends Type> List<T> seal(List<T> types) {
1893: if (null == types)
1894: return null;
1895:
1896: for (T t : types)
1897: t.seal();
1898: return Collections.unmodifiableList(types);
1899: }
1900:
1901: }
|