001: /**************************************************************************/
002: /* N I C E */
003: /* A high-level object-oriented research language */
004: /* (c) Daniel Bonniot 2000 */
005: /* */
006: /* This program is free software; you can redistribute it and/or modify */
007: /* it under the terms of the GNU General Public License as published by */
008: /* the Free Software Foundation; either version 2 of the License, or */
009: /* (at your option) any later version. */
010: /* */
011: /**************************************************************************/package mlsub.typing;
012:
013: import java.util.*;
014:
015: /**
016: A monomorphic type.
017:
018: @version $Date: 2005/06/21 18:31:00 $
019: @author Daniel Bonniot (d.bonniot@mail.dotcom.fr)
020: */
021: abstract public class Monotype implements mlsub.typing.lowlevel.Element {
022: /**
023: A zero length Monotype array.
024: Can be shared, since it's empty, thus immutable.
025: */
026: static final Monotype[] zeroMonotypes = new Monotype[0];
027:
028: final public boolean isConcrete() {
029: // No Monotype lives at runtime.
030: return false;
031: }
032:
033: /**
034: Returns true if this monotype is only made of
035: top-level, rigid type constructors
036: */
037: public boolean isRigid() {
038: return false;
039: }
040:
041: public final static boolean isRigid(Monotype[] ms) {
042: if (ms == null)
043: return true;
044:
045: for (int i = 0; i < ms.length; i++)
046: if (!(ms[i].isRigid()))
047: return false;
048:
049: return true;
050: }
051:
052: public boolean isExistential() {
053: // This is a default implementation. Only MonotypeVar need to be
054: // considered existential.
055: return false;
056: }
057:
058: /****************************************************************
059: * Substitution
060: ****************************************************************/
061:
062: /**
063: * Perform type symbol substitution inside the monotype.
064: *
065: * Does not need to create a new object,
066: * but must not modify the monotype.
067: *
068: * @param map a map from TypeSymbols to TypeSymbols
069: * @return a monotype with substitution performed
070: */
071: abstract Monotype substitute(Map map);
072:
073: final static Monotype[] substitute(java.util.Map map, Monotype[] ms) {
074: if (ms == null)
075: return null;
076:
077: Monotype[] res = new Monotype[ms.length];
078: for (int i = ms.length - 1; i >= 0; i--)
079: res[i] = ms[i].substitute(map);
080: return res;
081: }
082:
083: /****************************************************************
084: * Equivalent types
085: ****************************************************************/
086:
087: /**
088: Return the monotype used for type checking.
089:
090: Should be <tt>this</tt>, except in class MonotypeVar
091: where equivalent is a monotype with the correct Kind
092: once the kind is known.
093: */
094: public Monotype equivalent() {
095: return this ;
096: }
097:
098: /**
099: Return the head type constructor if this monotype is
100: of a known variance, or null.
101: */
102: public TypeConstructor head() {
103: return null;
104: }
105:
106: /**
107: If this monotype is functional, return its domain.
108: Otherwise return null.
109: */
110: public Monotype[] domain() {
111: return null;
112: }
113:
114: public boolean isUnknown() {
115: return false;
116: }
117:
118: public void setUnknown(boolean leq, boolean geq)
119: throws mlsub.typing.lowlevel.Unsatisfiable {
120: if (leq)
121: throw mlsub.typing.lowlevel.LowlevelUnsatisfiable.instance;
122:
123: if (geq) {
124: // We must check that this monotype is not non-null
125: TypeConstructor head = head();
126: if (head == null)
127: throw mlsub.typing.lowlevel.LowlevelUnsatisfiable.instance;
128: else
129: mlsub.typing.lowlevel.Engine.leq(NullnessKind.maybe,
130: head);
131:
132: Monotype raw = nice.tools.typing.Types.rawType(this );
133: mlsub.typing.lowlevel.Engine.leq(TopMonotype.instance, raw);
134: }
135: }
136:
137: /****************************************************************
138: * Simplification
139: ****************************************************************/
140:
141: /**
142: Propagate information for type simplification.
143: Not public.
144: */
145: abstract void tag(int variance);
146:
147: final static void tag(Monotype[] monotypes, int variance) {
148: if (monotypes == null)
149: return;
150:
151: for (int i = 0; i < monotypes.length; i++)
152: monotypes[i].tag(variance);
153: }
154:
155: /**
156: Return the monotype this one reduces to after simplification.
157: */
158: abstract Monotype canonify();
159:
160: final static Monotype[] canonify(Monotype[] monotypes) {
161: if (monotypes == null)
162: return null;
163:
164: Monotype[] res = new Monotype[monotypes.length];
165:
166: for (int i = 0; i < monotypes.length; i++)
167: res[i] = monotypes[i].canonify();
168:
169: return res;
170: }
171:
172: /****************************************************************
173: * Printing
174: ****************************************************************/
175:
176: /**
177: Print the monotype, using context information.
178: */
179: public String toString(boolean isNull, String suffix) {
180: String res = toString();
181: if (isNull)
182: res = "?" + res;
183: if (suffix != null)
184: res = res + suffix;
185: return res;
186: }
187: }
|