1(*
2    Original Poly version:
3    Title:      Operations on type structures.
4    Author:     Dave Matthews, Cambridge University Computer Laboratory
5    Copyright   Cambridge University 1985
6
7    ML translation and other changes:
8    Copyright (c) 2000
9        Cambridge University Technical Services Limited
10
11    Further development:
12    Copyright (c) 2000-9, 2012-2018, 2020 David C.J. Matthews
13
14    This library is free software; you can redistribute it and/or
15    modify it under the terms of the GNU Lesser General Public
16    License version 2.1 as published by the Free Software Foundation.
17    
18    This library is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    Lesser General Public License for more details.
22    
23    You should have received a copy of the GNU Lesser General Public
24    License along with this library; if not, write to the Free Software
25    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
26*)
27
28functor TYPE_TREE (
29    structure LEX : LEXSIG
30    structure STRUCTVALS : STRUCTVALSIG;
31    structure PRETTY : PRETTYSIG
32    structure CODETREE : CODETREESIG where type machineWord = Address.machineWord
33    structure EXPORTTREE: EXPORTTREESIG;
34    structure DEBUG: DEBUG
35
36    structure UTILITIES :
37    sig
38        val mapTable: ('a * 'a -> bool) ->
39                       {enter: 'a * 'b -> unit, lookup: 'a -> 'b option}
40        val splitString:   string -> { first:string, second:string }
41    end;
42
43    structure MISC :
44    sig
45        exception InternalError of string;
46  
47        val lookupDefault : ('a -> 'b option) -> ('a -> 'b option) -> 'a -> 'b option
48    end;
49
50    sharing LEX.Sharing = PRETTY.Sharing = EXPORTTREE.Sharing = STRUCTVALS.Sharing
51          = CODETREE.Sharing
52
53) :  TYPETREESIG =
54
55(*****************************************************************************)
56(*                  TYPETREE functor body                                    *)
57(*****************************************************************************)
58struct
59  open MISC;
60  open PRETTY;
61  
62  open STRUCTVALS;
63  open LEX;
64  open UTILITIES;
65  open CODETREE;
66  open EXPORTTREE
67
68  (* added 16/4/96 SPF *)
69  fun sameTypeVar (TypeVar x, TypeVar y) = sameTv (x, y)
70    | sameTypeVar _                      = false;
71
72  
73  fun isTypeVar          (TypeVar          _) = true
74    | isTypeVar          _ = false;
75     
76  fun isFunctionType     (FunctionType     _) = true
77    | isFunctionType     _ = false;
78
79  fun isEmpty             EmptyType           = true
80    | isEmpty            _ = false;
81    
82  fun isBadType           BadType             = true
83    | isBadType          _ = false;
84
85  val emptyType            = EmptyType;
86
87  fun typesTypeVar          (TypeVar          x) = x 
88    | typesTypeVar          _ = raise Match;
89    
90  fun typesFunctionType     (FunctionType     x) = x
91     | typesFunctionType     _ = raise Match;
92
93    (* This is really left over from an old definition. *)
94    fun tcEquivalent(TypeConstrs{identifier = TypeId {idKind = TypeFn(_, result), ...}, ...}) = result
95    |   tcEquivalent _ = raise InternalError "tcEquivalent: Not a type function"
96
97  (* A type construction is the application of a type constructor to
98     a sequence of types to yield a type. A construction may have a nil
99     list if it is a single type identifier such as ``int''. *)
100  
101  (* When a type constructor is encountered in the first pass this entry 
102     is put in. Subsequently a type constructor entry will be assigned to
103     it so that the types can be checked. *)
104
105(*************)
106
107    fun mkTypeVar (level, equality, nonunifiable, printable) = 
108        TypeVar (makeTv {value=emptyType, level=level, equality=equality,
109                         nonunifiable=nonunifiable, printable=printable});
110
111    fun mkTypeConstruction (name, typc, args, locations) =
112        TypeConstruction {name = name, constr = typc,
113                          args = args, locations = locations}
114
115    local
116        (* Turn a tuple into a record of the form {1=.., 2=... }*)
117        fun maptoRecord ([], _) = []
118          | maptoRecord (H::T, i) = 
119                {name=Int.toString i, typeof=H} :: maptoRecord (T,i+1)
120    in
121        fun mkProductType (typel: types list) =
122        let
123            val fields = maptoRecord (typel, 1)
124        in
125            LabelledType {recList = fields, fullList = FieldList(List.map #name fields, true)}
126        end
127    end
128
129  fun mkFunctionType (arg, result) = 
130      FunctionType {arg = arg, result = result};
131
132  fun mkOverloadSet [constr] =
133    (* If there is just a single constructor in the set we make
134       a type construction from it. *)
135        mkTypeConstruction(tcName constr, constr, nil, [])
136   | mkOverloadSet constrs = 
137    let
138        (* Make a type variable and point this at the overload set
139           so we can narrow down the overloading. *)
140        val var = mkTypeVar (generalisable, false, false, false)
141        val set = OverloadSet {typeset=constrs};
142    in
143        tvSetValue (typesTypeVar var, set);
144        var
145    end
146
147    fun mkLabelled (l, frozen) = 
148    let
149        val final = FieldList(map #name l, frozen)
150        val lab =
151            LabelledType {recList = l,
152                          fullList = if frozen then final else FlexibleList(ref final) }
153    in
154        if frozen
155        then lab
156        else
157        let
158           (* Use a type variable so that the record can be expanded.
159              This also provides a model (equality etc). for any fields that
160              are added later. *)
161            val var = mkTypeVar (generalisable, false, false, false)
162            val () =
163                if isTypeVar var
164                then tvSetValue (typesTypeVar var, lab)
165                else ();
166        in
167            var
168        end
169    end
170
171    (* Must remove leading zeros because the labels are compared by
172       string comparison. *)
173    fun mkLabelEntry (name, t) = 
174    let
175        fun stripZeros s = 
176            if size s <= 1  orelse String.str(String.sub(s, 0)) <> "0" 
177            then s
178            else stripZeros (String.substring(s, 1, size s-1));
179    in
180        {name = stripZeros name, typeof = t}
181    end;
182
183    (* Functions to construct the run-time representations of type constructor values,
184       type values and value constructors.  These are all tuples and centralising the
185       code here avoids having the offsets as integers at various places.
186       Monotype constructor and type values are almost the same except that
187       type values have the printer entry as the function whereas monotype
188       constructors have the print entry as a ref pointing to the function,
189       allowing addPrettyPrint to set a printer for the type.  The entries
190       for polytypes are functions that take the type values as arguments
191       and return the corresponding values. *)
192    structure TypeValue =
193    struct
194        val equalityOffset = 0
195        and printerOffset = 1
196        and boxnessOffset = 2
197        and sizeOffset = 3
198
199        local
200            (* Values used to represent boxness. *)
201            val boxedRepNever  = 0w1   (* Never boxed, always tagged e.g. bool *)
202            and boxedRepAlways = 0w2   (* Always boxed, never tagged e.g. function types *)
203            and boxedRepEither = 0w3   (* Either boxed or tagged e.g. (arbitrary precision) int *)
204            fun make n = mkConst(Address.toMachineWord n)
205            fun isCode n =
206                mkInlproc(mkEqualTaggedWord(mkLoadArgument 0, make n), 1, "test-box", [], 0)
207        in
208            val boxedNever  = make boxedRepNever
209            and boxedAlways = make boxedRepAlways
210            and boxedEither = make boxedRepEither
211            (* Test for boxedness.  This must be applied to the value extracted from
212               the "boxedness" field after applying to any base type arguments in
213               the case of a polytype constructor. *)
214            val isBoxedNever  = isCode boxedRepNever
215            and isBoxedAlways = isCode boxedRepAlways
216            and isBoxedEither = isCode boxedRepEither
217        end
218
219        (* Sizes are always a single word. *)
220        val singleWord = mkConst(Address.toMachineWord 0w1)
221
222        fun extractEquality idCode = mkInd(equalityOffset, idCode)
223        and extractPrinter idCode = mkInd(printerOffset, idCode)
224        and extractBoxed idCode = mkInd(boxnessOffset, idCode)
225        and extractSize idCode = mkInd(sizeOffset, idCode)
226
227        fun createTypeValue{eqCode, printCode, boxedCode, sizeCode} =
228            mkTuple[eqCode, printCode, boxedCode, sizeCode]
229    end
230
231    (* Value constructors are represented by tuples, either pairs for nullary constructors
232       or triples for constructors with arguments.  For nullary functions the "injection"
233       function is actually the value itself.  If this is a polytype all the entries are
234       functions that take the type values for the base types as arguments. *)
235    structure ValueConstructor =
236    struct
237        val testerOffset = 0
238        val injectorOffset = 1
239        val projectorOffset = 2
240
241        fun extractTest constrCode = mkInd(testerOffset, constrCode)
242        and extractInjection constrCode = mkInd(injectorOffset, constrCode)
243        and extractProjection constrCode = mkInd(projectorOffset, constrCode)
244
245        fun createValueConstr{testMatch, injectValue, projectValue} = mkTuple[testMatch, injectValue, projectValue]
246        fun createNullaryConstr{ testMatch, constrValue } = mkTuple[testMatch, constrValue]
247    end
248
249    (* Eqtypes with built-in equality functions.  The printer functions are all replaced in the basis. *)
250    local
251        open Address PRETTY TypeValue
252        fun defaultMonoTypePrinter _ = PrettyString "?"
253        fun defaultPolyTypePrinter _ _ = PrettyString "?"
254
255        fun eqAndPrintCode (eqCode, nArgs, boxed) =
256        let
257            val code =
258                if nArgs = 0
259                then createTypeValue{
260                        eqCode=eqCode,
261                        printCode=mkConst (toMachineWord (ref defaultMonoTypePrinter)),
262                        boxedCode = boxed,
263                        sizeCode = singleWord
264                        }
265                else createTypeValue{
266                        eqCode=mkInlproc(eqCode, nArgs, "eq-helper()", [], 0),
267                        printCode=mkConst (toMachineWord (ref defaultPolyTypePrinter)),
268                        boxedCode = mkInlproc(boxed, nArgs, "boxed-helper()", [], 0),
269                        sizeCode = mkInlproc(singleWord, nArgs, "size-helper()", [], 0)
270                        }
271        in
272            Global (genCode(code, [], 0) ())
273        end
274
275        fun makeConstr(name, fullName, eqFun, boxed) =
276            makeTypeConstructor (name, [],
277                makeFreeId(0, eqAndPrintCode(eqFun, 0, boxed), true, basisDescription fullName),
278                [DeclaredAt inBasis])
279    
280        (* since code generator relies on these representations,
281           we may as well export them *)
282
283        (* Strings are now always vectors whose first word is the length.
284           The old special case for single-character strings has been removed. *)
285        local
286            val stringEquality =
287                mkInlproc(
288                    (* This previously checked for pointer equality first.  That has
289                       been removed.
290                       Test the lengths first and only do the byte comparison if
291                       they are the same.  This seems to save more time than including
292                       the length word in the byte comparison. *)
293                    mkCand(
294                        mkEqualPointerOrWord( (* Because we're not actually tagging these we use pointerEq here. *)
295                            mkLoadOperation(LoadStoreUntaggedUnsigned, mkLoadArgument 0, CodeZero),
296                            mkLoadOperation(LoadStoreUntaggedUnsigned, mkLoadArgument 1, CodeZero)),
297                        mkBlockOperation{kind=BlockOpEqualByte, leftBase=mkLoadArgument 0, rightBase=mkLoadArgument 1,
298                                leftIndex=mkConst(toMachineWord wordSize), rightIndex=mkConst(toMachineWord wordSize),
299                                    (* Use argument 1 here rather than 0.  We could use either but this works
300                                       better when we're using equality for pattern matching since it
301                                       gets the length of the constant string.  It also works better
302                                       for the, to me, more natural ordering of variable=constant. *)
303                                length=mkLoadOperation(LoadStoreUntaggedUnsigned, mkLoadArgument 1, CodeZero)
304                        }
305                    ),
306                    2, "stringEquality", [], 0)
307        in
308            val stringEquality = stringEquality
309        end
310
311        local
312            (* Arbitrary precision values are normalised so if a value can be represented
313               as a tagged fixed precision value it will be.
314               Unlike strings it is much more likely that the value will be short so we
315               generate equality as a test that handles the short case as inline code and
316               the long case as a function call.  If either argument is a short constant
317               this will be optimised away so the test will reduce to a test on whether
318               the value equals the constant. *)
319            val intEquality =
320                mkEnv(
321                    [mkDec(0,
322                        (* Long-form equality - should not be inlined. *)
323                        mkProc(
324                            (* Equal if  signs are the same ... *)
325                            mkCand(
326                                mkEqualTaggedWord(
327                                    mkUnary(BuiltIns.MemoryCellFlags, mkLoadArgument 0),
328                                    mkUnary(BuiltIns.MemoryCellFlags, mkLoadArgument 1)
329                                ),
330                                mkEnv(
331                                    [mkDec(0, mkUnary(BuiltIns.MemoryCellLength, mkLoadArgument 1))],
332                                    mkCand(
333                                        (* ... and the lengths are equal ... *)
334                                        mkEqualTaggedWord(
335                                            mkUnary(BuiltIns.MemoryCellLength, mkLoadArgument 0),
336                                            mkLoadLocal 0
337                                        ),
338                                        (* ... and they're byte-wise equal .*)
339                                        mkBlockOperation{kind=BlockOpEqualByte, leftBase=mkLoadArgument 0, rightBase=mkLoadArgument 1,
340                                            leftIndex=CodeZero, rightIndex=CodeZero,
341                                            length=mkBinary(BuiltIns.WordArith BuiltIns.ArithMult,
342                                                mkConst(toMachineWord RunCall.bytesPerWord), mkLoadLocal 0)}
343                                    )
344                                )
345                            ),
346                            2, "arbitraryPrecisionEquality", [], 1)
347                        )
348                    ],
349                mkInlproc(
350                    mkCor( (* Either they're equal... *)
351                           (* N.B. The values could be short or long.  That's particularly important
352                              if we have a series of tests against short constants.  If we convert it to
353                              an indexed case we MUST check that the value is short before computing
354                              the index. *)
355                        mkEqualPointerOrWord(mkLoadArgument 0, mkLoadArgument 1),
356                        (* .. or if either is short the result is false ... *)
357                        mkCand(
358                            mkCand(
359                                mkNot(mkIsShort(mkLoadArgument 0)),
360                                mkNot(mkIsShort(mkLoadArgument 1))
361                            ),
362                            (* ... otherwise we have to test the vectors. *)
363                            mkEval(mkLoadClosure 0, [mkLoadArgument 0, mkLoadArgument 1])
364                        )
365                     ),
366                     2, "intInfEquality", [mkLoadLocal 0], 0)
367                )
368        in
369            (* Code-generate the function and return the inline part. 
370               We need to set the maximum inline size here to ensure the long form
371               code is not inlined.  It would be better to have a way of turning off
372               inlining for specific functions. *)
373            val intEquality = genCode(intEquality, [Universal.tagInject DEBUG.maxInlineSizeTag 5], 1) ()
374        end
375    in
376        val fixedIntConstr = makeConstr("int",  "FixedInt.int", equalTaggedWordFn, boxedNever) (* Fixed precision is always short *)
377        val intInfConstr = makeConstr("int",    "IntInf.int", intEquality, boxedEither)
378        val charConstr   = makeConstr("char",   "char", equalTaggedWordFn, boxedNever) (* Always short *)
379        val stringConstr = makeConstr("string", "string", stringEquality, boxedEither (* Single chars are unboxed. *))
380        val wordConstr   = makeConstr("word",   "word", equalTaggedWordFn, boxedNever)
381
382        (* Ref is a datatype with a single constructor.  The constructor is added in INITIALISE.
383           Equality is special for "'a ref", "'a array" and "'a Array2.array".  They permit equality
384           even if the 'a is not an eqType. *)
385        val refConstr =
386            makeTypeConstructor 
387                ("ref",
388                [makeTv {value=EmptyType, level=generalisable, equality=false, nonunifiable=false, printable=false}],
389                makeFreeId(1, eqAndPrintCode(equalPointerOrWordFn, 1, boxedAlways), true, basisDescription "ref"),
390                [DeclaredAt inBasis]);
391        val arrayConstr =
392            makeTypeConstructor 
393                ("array",
394                [makeTv {value=EmptyType, level=generalisable, equality=false, nonunifiable=false, printable=false}],
395                makeFreeId(1, eqAndPrintCode(equalPointerOrWordFn, 1, boxedAlways), true, basisDescription "Array.array"),
396                [DeclaredAt inBasis]);
397        val array2Constr =
398            makeTypeConstructor 
399                ("array",
400                [makeTv {value=EmptyType, level=generalisable, equality=false, nonunifiable=false, printable=false}],
401                makeFreeId(1, eqAndPrintCode(equalPointerOrWordFn, 1, boxedAlways), true, basisDescription "Array2.array"),
402                [DeclaredAt inBasis]);
403        val byteArrayConstr =
404            makeTypeConstructor 
405                ("byteArray", [],
406                makeFreeId(0, eqAndPrintCode(equalPointerOrWordFn, 0, boxedAlways), true, basisDescription "byteArray"),
407                [DeclaredAt inBasis]);
408        (* Bool is a datatype.  The constructors are added in INITIALISE. *)
409        val boolConstr =
410            makeTypeConstructor 
411                ("bool", [], makeFreeId(0, eqAndPrintCode(equalTaggedWordFn, 0, boxedNever), true, basisDescription "bool"),
412                [DeclaredAt inBasis]);
413    end
414
415    (* These polytypes allow equality even if the type argument is not an equality type. *)
416    fun isPointerEqType id =
417        sameTypeId (id, tcIdentifier refConstr) orelse
418        sameTypeId (id, tcIdentifier arrayConstr) orelse
419        sameTypeId (id, tcIdentifier array2Constr) orelse
420        sameTypeId (id, tcIdentifier byteArrayConstr)
421
422    (* Non-eqtypes *)
423    local
424        open Address PRETTY TypeValue
425
426        fun makeType(name, descr, boxed) =
427        let
428            fun defaultPrinter _ = PrettyString "?"
429            val code =
430                createTypeValue{
431                    eqCode=CodeZero (* No equality. *),
432                    printCode=mkConst (toMachineWord (ref defaultPrinter)),
433                    boxedCode=boxed,
434                    sizeCode=singleWord
435                }
436        in
437            makeTypeConstructor (
438                name, [], makeFreeId(0, Global (genCode(code, [], 0) ()), false, descr),
439                [DeclaredAt inBasis])
440        end
441    in
442        val realConstr   = makeType("real", basisDescription "real", boxedAlways(* Currently*)) (* Not an eqtype in ML97. *)
443        (* Short real: Real32.real *)
444        val floatConstr  =
445            makeType("real", basisDescription "real",
446                if RunCall.bytesPerWord <= 0w4 then boxedAlways else boxedNever)
447        val exnConstr    = makeType("exn", basisDescription "exn", boxedAlways);
448        (* "undefConstr" is used as a place-holder during parsing for the actual type constructor.
449           If the type constructor is not found this may appear in an error message. *)
450        val undefConstr  =
451            makeType("undefined", { location = inBasis, description = "Undefined", name = "undefined" }, boxedEither);
452    end
453
454    (* The unit type is equivalent to the empty record. *)
455    val unitConstr   =
456        makeTypeConstructor ("unit", [],
457            makeTypeFunction({ location = inBasis, description = "unit", name = "unit" },
458            ([], LabelledType {recList = [], fullList = FieldList([], true)})),
459            [DeclaredAt inBasis]);
460
461
462  (* Type identifiers bound to standard type constructors. *)
463
464    val unitType = mkTypeConstruction ("unit", unitConstr, [], [])
465
466    val fixedIntType = mkTypeConstruction ("int",   fixedIntConstr,    [], [])
467    val stringType = mkTypeConstruction ("string",  stringConstr, [], [])
468    val boolType   = mkTypeConstruction ("bool",    boolConstr,   [], [])
469    val exnType    = mkTypeConstruction ("exn",     exnConstr,    [], [])
470          
471    fun isUndefined cons = sameTypeId (tcIdentifier cons, tcIdentifier undefConstr);
472    val isUndefinedTypeConstr = isUndefined
473
474    (* Test if a type is the undefined constructor. *)
475    fun isUndefinedType(TypeConstruction{constr, ...}) = isUndefined constr
476    |   isUndefinedType _ = false
477
478    (* Similar to alphabetic ordering except that shorter labels come before longer ones.
479       This has the advantage that numerical labels are compared by their numerical order
480       i.e. 1 < 2 < 10 whereas alphabetic ordering puts "1" < "10" < "2". *)
481    fun compareLabels (a : string, b : string) : int = 
482    if size a = size b 
483    then if a = b then 0 else if a < b then ~1 else 1
484    else if size a < size b then ~1 else 1;
485
486    (* Sort using the label ordering.
487       A simple sort routine - particularly if the list is already sorted. *)
488    fun sortLabels [] = []
489    |   sortLabels (s::rest) =
490    let
491        fun enter s _    [] = [s]
492          | enter s name (l as ( (h as {name=hname, ...}) :: t)) =
493        let
494            val comp = compareLabels (name, hname);
495        in
496            if comp <= 0 then s :: l else h :: enter s name t
497        end;
498    in  
499        enter s (#name s) (sortLabels rest)
500    end
501
502  (* Chains down a list of type variables returning the type they are
503     bound to. As a side-effect it also points all the type variables
504     at this type to reduce the need for future chaining and to free
505     unused type variables. Normally a type variable points to at most
506     one other, which then points to "empty". However if we have unified
507     two type variables by pointing one at the other, there may be type
508     variables which pointed to the first and which cannot be found and
509     redirected at the second until they themselves are examined. *)
510     
511    fun eventual (t as (TypeVar tv)) : types =
512    let
513        (* Note - don't change the level/copy information - the only type
514           variable with this correct is the one at the end of the list. *)
515        val oldVal = tvValue tv
516        val newVal = eventual oldVal;   (* Search that *)
517    in
518        (* Update the type variable to point to the last in the chain.
519         We don't do this if the value hasn't changed.  The reason for
520         that was that assignment to refs in the database in the old
521         persistent store system was very expensive and we wanted to avoid
522         unnecessary assignments.  This special case could probably be removed. *)
523        if PolyML.pointerEq(oldVal, newVal)
524        then ()
525        else tvSetValue (tv, newVal); (* Put it on *)
526        case newVal of
527            EmptyType => t (* Not bound to anything - return the type variable *)
528        |   LabelledType (r as { recList, fullList }) =>
529            if List.length recList = List.length(recordFields r)
530            then (* All the generic fields are present so we don't need to do anything. *)
531                if recordIsFrozen r then newVal else t
532            else (* We need to add fields from the generic. *)
533            let
534                (* Add any fields from the generic that aren't present in this instance. *)
535                fun createNewField name =
536                        { name = name,
537                          (* The new type variable has to be created with the same properties
538                             as if we had first generalised it from the generic and then
539                             unified with this instance.
540                             The level is inherited from the instance since the generic
541                             will always have level = generalisable.  Nonunifiable must be false. *)
542                            typeof = mkTypeVar (tvLevel tv, tvEquality tv, false, tvPrintity tv)}
543
544                fun addToInstance([], []) = []
545                |   addToInstance(generic :: geRest, []) = createNewField generic :: addToInstance(geRest, [])
546                |   addToInstance([], instance) = instance
547                        (* This case can occur if we are producing an error message because of
548                           a type-incorrect program so we just ignore it. *)
549                |   addToInstance(generic :: geRest, inst as instance :: iRest) =
550                    let
551                        val order = compareLabels (generic, #name instance);
552                    in
553                        if order = 0 (* Equal *)
554                        then instance :: addToInstance(geRest, iRest)
555                        else if order < 0 (* generic name < instance name *)
556                        then createNewField generic :: addToInstance(geRest, inst)
557                        else (* This is another case that can occur with type-incorrect code. *)
558                            instance :: addToInstance(generic :: geRest, iRest)
559                    end
560
561                val newList = addToInstance(recordFields r, recList)
562                val newRecord =
563                    LabelledType {recList = newList, fullList = fullList}
564            in
565                tvSetValue(tv, newRecord);
566                if recordIsFrozen r then newRecord else t
567            end
568 
569        |   OverloadSet _ => t (* Return the set of types. *)
570
571        |   _ => newVal (* Return the type it is bound to *)
572    end
573    
574    | eventual t (* not a type variable *) = t;
575
576
577    (* Apply a function to every element of a type. *)
578    fun foldType f =
579    let
580        fun foldT typ v =
581        let
582            val t   = eventual typ;
583            val res = f t v; (* Process this entry. *)
584        in
585            case t of
586                TypeVar tv => foldT (tvValue tv) res
587
588            |   TypeConstruction {args, ...} => (* Then process the arguments. *)
589                    List.foldr (fn (t, v) => foldT t v) res args
590           
591            |   FunctionType {arg, result} => foldT arg (foldT result res)
592    
593            |   LabelledType {recList,...} =>
594                    List.foldr (fn ({ typeof, ... }, v) => foldT typeof v) res recList
595
596            |   BadType => res
597         
598            |   EmptyType => res
599          
600            |   OverloadSet _ => res
601        end
602    in
603        foldT
604    end;
605
606    (* Checks to see whether a labelled record is in the form of
607     a product i.e. 1=, 2=   We only need this for prettyprinting.
608     Zero-length records (i.e. unit) and singleton records are not
609     considered as tuples. *)
610    fun isProductType(LabelledType(r as {recList=recList as _::_::_, ...})) =
611    let
612        fun isRec [] _ = true
613         |  isRec ({name, ...} :: l) n =
614                name = Int.toString n andalso isRec l (n+1)
615    in
616        recordIsFrozen r andalso isRec recList 1
617    end
618    | isProductType _ = false;
619
620
621    (* Test to see is a type constructor is in an overload set. *)
622    fun isInSet(tcons: typeConstrs, (H::T): typeConstrs list) =
623            sameTypeId (tcIdentifier tcons, tcIdentifier H) orelse isInSet(tcons, T)
624    |   isInSet(_, []: typeConstrs list) = false
625
626    val prefInt = ref fixedIntConstr
627
628    (* Returns the preferred overload if there is one. *)
629    fun preferredOverload typeset =
630        if isInSet(!prefInt, typeset)
631        then SOME(!prefInt)
632        else if isInSet(realConstr, typeset)
633        then SOME realConstr
634        else if isInSet(wordConstr, typeset)
635        then SOME wordConstr
636        else if isInSet(charConstr, typeset)
637        then SOME charConstr
638        else if isInSet(stringConstr, typeset)
639        then SOME stringConstr
640        else NONE
641
642    fun setPreferredInt c = prefInt := c
643
644    fun equalTypeIds(x, y) =
645    let
646        (* True if two types are equal. *)
647        fun equalTypes (TypeConstruction{constr=xVal, args=xArgs, ...},
648                        TypeConstruction{constr=yVal, args=yArgs, ...}) =
649            equalTypeIds(tcIdentifier xVal, tcIdentifier yVal)
650                andalso equalTypeLists (xArgs, yArgs)
651    
652        | equalTypes (FunctionType x, FunctionType y) = 
653            equalTypes (#arg x, #arg y)   andalso 
654            equalTypes (#result x, #result y)
655                 
656        | equalTypes (LabelledType x, LabelledType y) =
657            recordIsFrozen x andalso recordIsFrozen y andalso  
658            equalRecordLists (#recList x, #recList y)
659
660        | equalTypes (TypeVar x, TypeVar y)  = sameTv (x, y)
661
662        | equalTypes (EmptyType, EmptyType) = true
663
664        | equalTypes _ = false
665                              
666        and equalTypeLists ([], [])    = true
667        |   equalTypeLists (x::xs, y::ys) =
668               equalTypes(x, y) andalso equalTypeLists (xs, ys)
669        |   equalTypeLists _           = false
670
671        and equalRecordLists ([],        [])    = true
672        |   equalRecordLists (x::xs, y::ys) =
673               #name x = #name y andalso 
674               equalTypes(#typeof x, #typeof y) andalso equalRecordLists (xs, ys)
675        |   equalRecordLists _             = false
676    in
677        case (x, y) of
678            (TypeId{idKind=TypeFn(_, xEquiv), ...}, TypeId{idKind=TypeFn(_, yEquiv), ...}) =>
679                equalTypes(xEquiv, yEquiv)
680        |   _ => sameTypeId(x, y) 
681    end
682
683    (* See if the types are the same. This is a bit of a fudge, but saves carrying
684       around a flag saying whether the structures were copied. This is only an
685       optimisation. If the values are different it will not go wrong. *)
686    val identical : types * types -> bool = PolyML.pointerEq
687    and identicalConstr : typeConstrs * typeConstrs -> bool = PolyML.pointerEq
688    and identicalList : 'a list * 'a list -> bool = PolyML.pointerEq
689
690    (* Copy a type, avoiding copying type structures unnecessarily.
691       Used to make new type variables for all distinct type variables when
692       generalising polymorphic functions, and to make new type stamps for
693       type constructors when generalising signatures. *)
694    fun copyType (at, copyTypeVar, copyTypeConstr) =
695    let
696        fun copyList [] = []
697        |   copyList (l as (h :: t)) =
698        let
699            val h' = copyType (h, copyTypeVar, copyTypeConstr);
700            val t' = copyList t;
701        in
702            if identical (h', h) andalso identicalList (t', t)
703            then l
704            else h' :: t'
705        end  (* copyList *);
706
707        fun copyRecordList [] = []
708        |   copyRecordList (l as ({name, typeof} :: t)) =
709        let
710            val typeof' = copyType (typeof, copyTypeVar, copyTypeConstr);
711            val t' = copyRecordList t;
712        in
713            if identical (typeof', typeof) andalso identicalList (t', t)
714            then l
715            else {name=name, typeof=typeof'} :: t'
716        end  (* copyList *);
717
718        val atyp = eventual at;
719    in
720        case atyp of
721            TypeVar _ =>  (* Unbound type variable, flexible record or overloading. *)
722                copyTypeVar atyp
723    
724        |   TypeConstruction {constr, args, locations, ...} => 
725            let
726                val copiedArgs   = copyList args;
727                val copiedConstr = copyTypeConstr constr;
728                (* Use the name from the copied constructor.  This will normally
729                   be the same as the original EXCEPT in the case where we are
730                   using copyType to generate copies of the value constructors of
731                   replicated datatypes. *)
732                val copiedName = tcName copiedConstr
733            in
734                if identicalList (copiedArgs, args) andalso
735                    identicalConstr (copiedConstr, constr)
736                then atyp 
737                else (* Must copy it. *) 
738                    mkTypeConstruction (copiedName, copiedConstr, copiedArgs, locations)
739            end 
740           
741        |   FunctionType {arg, result} => 
742            let
743                val copiedArg  = copyType (arg,    copyTypeVar, copyTypeConstr);
744                val copiedRes  = copyType (result, copyTypeVar, copyTypeConstr);
745            in
746                if identical (copiedArg, arg) andalso 
747                    identical (copiedRes, result)
748                then atyp 
749                else FunctionType {arg = copiedArg, result = copiedRes}
750            end 
751              
752        |   LabelledType {recList, fullList} =>
753                (* Rigid labelled records only.  Flexible ones are treated as type vars. *)
754            let
755                val copiedList = copyRecordList recList
756            in
757                if identicalList (copiedList, recList)
758                then atyp 
759                else LabelledType {recList = copiedList, fullList = fullList}
760            end
761                        
762        |   EmptyType =>
763                EmptyType
764
765        |   BadType =>
766                BadType
767        
768        |   OverloadSet _ =>
769                raise InternalError "copyType: OverloadSet found"
770
771    end (* copyType *);
772
773    (* Copy a type constructor if it is Bound and in the required range.  If this refers to a type
774       function copies that as well. Does not copy value constructors. *)
775    fun copyTypeConstrWithCache (tcon, typeMap, _, mungeName, cache) =
776        case tcIdentifier tcon of
777            TypeId{idKind = TypeFn(args, equiv), description, access, ...} =>
778            let
779                val copiedEquiv =
780                    copyType(equiv, fn x => x,
781                        fn tcon =>
782                            copyTypeConstrWithCache (tcon, typeMap, fn x => x, mungeName, cache))
783            in
784                if identical (equiv, copiedEquiv)
785                then tcon (* Type is identical and we don't want to change the name. *)
786                else (* How do we find a type function? *)
787                    makeTypeConstructor (mungeName(tcName tcon), args,
788                        TypeId {
789                            access = access, description = description, idKind = TypeFn(args, copiedEquiv)},
790                            tcLocations tcon)
791
792            end
793
794       |    id =>
795            (
796                case typeMap id of
797                    NONE =>
798                    (
799                        (*print(concat[tcName tcon, " not copied\n"]);*)
800                        tcon (* No change *)
801                    )
802                |   SOME newId =>
803                    let
804                        val name = #second(splitString (tcName tcon))
805                        (* We must only match here if they're really the same. *)
806                        fun cacheMatch tc =
807                            equalTypeIds(tcIdentifier tc, newId)
808                                andalso #second(splitString(tcName tc)) = name
809                    in
810                        case List.find cacheMatch cache of
811                            SOME tc =>
812                            (
813                                (*print(concat[tcName tcon, " copied as ", tcName tc, "\n"]);*)
814                                tc (* Use the entry from the cache. *)
815                            )
816                        |   NONE =>
817                            (* Either a hidden identifier or alternatively this can happen as part of
818                               the matching process.
819                               When matching a structure to a signature we first match up the type
820                               constructors then copy the type of each value replacing bound type IDs
821                               with the actual IDs as part of the checking process.
822                               We will return SOME newId but we don't have a
823                               cache so return NONE for List.find. *)
824                            let
825                                val newName = mungeName(tcName tcon)
826                            in
827                                (*print(concat[tcName tcon, " not cached\n"]);*)
828                                makeTypeConstructor(newName, tcTypeVars tcon, newId, tcLocations tcon)
829                            end
830                    end
831            )
832
833    (* Exported version. *)
834    fun copyTypeConstr (tcon, typeMap, copyTypeVar, mungeName) =
835        copyTypeConstrWithCache(tcon, typeMap, copyTypeVar, mungeName, [])
836
837    (* Compose typeID maps.  If the first map returns a Bound id we apply the second otherwise
838       just return the result of the first. *)
839    fun composeMaps(m1, m2) n =
840    let
841        fun map2 (TypeId{idKind=Bound{ offset, ...}, ...}) = m2 offset
842
843        |   map2 (id as TypeId{idKind=Free _, ...}) = id
844
845        |   map2 (TypeId{idKind=TypeFn(args, equiv), access, description, ...}) =
846            let
847                fun copyId(TypeId{idKind=Free _, ...}) = NONE
848                |   copyId id = SOME(map2 id)
849                (* If it's a type function e.g. this was a "where type" we have to apply the
850                   map to any type identifiers in the type. *)
851                val copiedEquiv =
852                    copyType(equiv, fn x => x,
853                        fn tcon => copyTypeConstr (tcon, copyId, fn x => x, fn y => y))
854            in
855                TypeId{idKind = TypeFn(args, copiedEquiv), access=access, description=description}
856            end
857    in
858        map2(m1 n)
859    end
860
861    (* Basic procedure to print a type structure. *)
862    type printTypeEnv =
863        { lookupType: string -> (typeConstrSet * (int->typeId) option) option,
864          lookupStruct: string -> (structVals * (int->typeId) option) option}
865
866    val emptyTypeEnv = { lookupType = fn _ => NONE, lookupStruct = fn _ => NONE }
867
868    (* Test whether two type constructors are the same after mapping.
869       This is used to try to find the correct "path" to a type constructor
870       when printing. *)
871    fun eqTypeConstrs(xTypeCons, xMap, yTypeCons, yMap) =
872    let
873        fun id x = x
874        fun copyId (SOME mapTypeId) (TypeId{idKind=Bound{ offset, ...}, ...}) = SOME(mapTypeId offset)
875        |   copyId _ _ = NONE
876        val mappedX = copyTypeConstr(xTypeCons, copyId xMap, id, id)
877        and mappedY = copyTypeConstr(yTypeCons, copyId yMap, id, id)
878    in
879        equalTypeIds(tcIdentifier mappedX, tcIdentifier mappedY)
880    end
881
882    (* prints a block of items *)
883    fun tDisp (t : types, depth : FixedInt.int, typeVarName : typeVarForm -> string, env: printTypeEnv,
884               sigMap: (int->typeId)option) : pretty =
885    let
886        (* prints a block of items *)
887        fun dispP (t : types, depth : FixedInt.int) : pretty =
888        let
889            (* prints a block of items *)
890            fun parenthesise depth t =
891            if depth <= 1
892            then PrettyString "..."
893            else
894                PrettyBlock (0, false, [],
895                    [
896                        PrettyString "(",
897                        dispP (t, depth - 1),
898                        PrettyString ")"
899                    ]);
900    
901            (* prints a sequence of items *)
902            fun prettyList [] _ _: pretty list = []
903
904            |   prettyList [H] depth separator =
905                let
906                    val v = eventual H;
907                in
908                    if separator = "*" andalso
909                        (isFunctionType v orelse isProductType v)
910                    then (* Must bracket the expression *) [parenthesise depth v]
911                    else [dispP (v, depth)]
912                end
913
914            |   prettyList (H :: T) depth separator =
915                if depth <= 0
916                then [PrettyString "..."]
917                else
918                let
919                    val v = eventual H;
920                in
921                    PrettyBlock (0, false, [],
922                        [(if separator = "*" andalso
923                           (isFunctionType v orelse isProductType v)
924                        then (* Must bracket the expression *) parenthesise depth v
925                        else dispP (v, depth)),
926                        PrettyBreak (if separator = "," then 0 else 1, 0),
927                        PrettyString separator
928                        ]) ::
929                    PrettyBreak (1, 0) ::
930                    prettyList T (depth - 1) separator
931                end;
932        
933            val typ = eventual t; (* Find the real type structure *)
934        in 
935            case typ of
936                TypeVar tyVar =>
937                let
938                    val tyVal : types = tvValue tyVar;
939                in
940                    case tyVal of
941                        EmptyType => PrettyString (typeVarName tyVar)
942                    |   _         => dispP (tyVal, depth)
943                end
944      
945                (* Type construction. *)
946            |   TypeConstruction {args, name, constr=typeConstructor, ...} =>
947                let
948                    val constrName = (* Use the type constructor name unless we're had an error. *)
949                        if isUndefined typeConstructor then name else tcName typeConstructor
950
951                    (* There are three possible cases: we may not find any type with the
952                       name, we may look up the name and find the type or we may look up the
953                       name and find a different type. *)
954                    datatype isFound = NotFound | FoundMatch | FoundNotMatch
955                    
956                    (* If we're printing a value that refers to a type constructor we
957                       want to print the correct amount of any structure prefix for the
958                       current context. *)
959                    fun findType (_, []) = NotFound
960                    |   findType ({ lookupType, ... }, [typeName]) =
961                        (
962                            (* This must be the name of a type. *)
963                            case lookupType typeName of
964                                SOME (t, map) =>
965                                    if eqTypeConstrs(typeConstructor, sigMap, tsConstr t, map)
966                                    then FoundMatch else FoundNotMatch
967                            |   NONE => NotFound
968                        )
969                    |   findType ({ lookupStruct, ... }, structName :: tail) =
970                        (
971                            (* This must be the name of a structure.  Does it contain our type? *)
972                            case lookupStruct structName of
973                                SOME(Struct { signat, ...}, map) =>
974                                    let
975                                        val Signatures { tab, typeIdMap, ...} = signat
976                                        val Env { lookupType, lookupStruct, ...} = makeEnv tab
977                                        val newMap =
978                                            case map of
979                                                SOME map => composeMaps(typeIdMap, map)
980                                            |   NONE => typeIdMap
981                                        fun subLookupType s =
982                                            case lookupType s of NONE => NONE | SOME t => SOME(t, SOME newMap)
983                                        fun subLookupStruct s =
984                                            case lookupStruct s of NONE => NONE | SOME t => SOME(t, SOME newMap)
985                                    in
986                                        findType({lookupType=subLookupType, lookupStruct=subLookupStruct}, tail)
987                                    end
988                            |   NONE => NotFound
989                        )
990
991                    (* See if we have this type in the current environment or in some structure in
992                       the current environment.  The name we have may be a full structure path. *)
993                    fun nameToList ("", l) = (l, NotFound) (* Not there. *)
994                    |   nameToList (s, l) = 
995                        let
996                            val { first, second } = splitString s
997                            val currentList = second :: l
998                        in
999                            case findType(env, currentList) of
1000                                FoundMatch => (currentList, FoundMatch)
1001                            |   FoundNotMatch =>
1002                                (
1003                                    case nameToList(first, currentList) of
1004                                        result as (_, FoundMatch) => result
1005                                    |   (l, _) => (l, FoundNotMatch)
1006                                )
1007                            |   NotFound => nameToList(first, currentList)
1008                        end
1009                    (* Try the type constructor name first.  This is usually accurate.  If not
1010                       fall back to the type identifier.  This may be needed in rarer cases. *)
1011                    val names =
1012                        case nameToList(constrName, []) of
1013                            (names, FoundMatch) => names (* Found the type constructor name. *)
1014                        |   (names, f) =>
1015                            let
1016                                (* Try the type identifier name. *)
1017                                val TypeId { description = { name=idName, ...}, ...} =
1018                                    case (sigMap, tcIdentifier typeConstructor) of
1019                                    (SOME map, TypeId{idKind=Bound{offset, ...}, ...}) => map offset
1020                                |   (_, id) => id
1021                                (* Only add "?" if we actually found a type with the required
1022                                   name but it wasn't the right one.  This allows us to print a
1023                                   sensible result where the type has been shadowed but doesn't
1024                                   affect situations such as where we create a unique type name
1025                                   for a free type variable. *)
1026                                fun addQuery n =
1027                                    case f of FoundNotMatch => "?" :: n | _ => n
1028                            in
1029                                if idName = "" then addQuery names
1030                                else
1031                                case nameToList(idName, []) of
1032                                    (idNames, FoundMatch) => idNames
1033                                |   (_, _) => addQuery names (* Print it as "?.t".  This isn't ideal but will help in
1034                                                              situations where we have redefined "t". *)
1035                            end
1036                    val newName = String.concatWith "." names
1037                    (* Get the declaration position for the type constructor. *)
1038                    val constrContext =
1039                        if isUndefined typeConstructor then []
1040                        else
1041                        (
1042                            case List.find(fn DeclaredAt _ => true | _ => false) (tcLocations typeConstructor) of
1043                                SOME(DeclaredAt loc) => [ContextLocation loc]
1044                            |   _ => []
1045                        )
1046                    val constructorEntry = 
1047                        PrettyBlock(0, false, constrContext, [PrettyString newName(*constrName*)])
1048                in
1049                    case args of
1050                        [] => constructorEntry
1051                    |   args as hd :: tl =>
1052                        let
1053                            val argVal = eventual hd;
1054                        in
1055                            PrettyBlock (0, false, [],
1056                            [
1057                                (* If we have just a single argument and it's just a type constructor
1058                                   or a construction we don't need to parenthesise it. *)
1059                                if null tl andalso not (isProductType argVal orelse isFunctionType argVal)
1060                                then dispP (argVal, depth - 1)
1061                                else if depth <= 1
1062                                then PrettyString "..."
1063                                else PrettyBlock(0, false, [],
1064                                         [PrettyString "(", PrettyBreak (0, 0)]
1065                                         @ prettyList args (depth - 1) ","
1066                                         @ [PrettyBreak (0, 0), PrettyString ")"]
1067                                     ),
1068                                PrettyBreak(1, 0),
1069                                constructorEntry (* The constructor. *)
1070                            ])
1071                        end
1072                end
1073        
1074            |   FunctionType {arg, result} =>
1075                if depth <= 0
1076                then PrettyString "..."
1077                else (* print out in infix notation *)
1078                let
1079                    val evArg = eventual arg;
1080                in
1081                    PrettyBlock (0, false, [],
1082                        [
1083                        (* If the argument is a function it must be printed as (a-> b)->.. *)
1084                        if isFunctionType evArg 
1085                        then parenthesise depth evArg
1086                        else dispP (evArg, depth - 1),
1087                        PrettyBreak(1, 2),
1088                        PrettyString "->",
1089                        PrettyBreak (1, 2),
1090                        dispP (result, depth - 1)
1091                        ])
1092                end
1093                     
1094            |   LabelledType (r as {recList, ...}) =>
1095                if depth <= 0
1096                then PrettyString "..."
1097                else if isProductType typ
1098                then (* Print as a product *)
1099                    PrettyBlock (0, false, [], (* Print them as t1 * t2 * t3 .... *)
1100                        prettyList (map (fn {typeof, ...} => typeof) recList) depth "*")
1101                else (* Print as a record *)
1102                let
1103                    (* The ordering on fields is designed to allow mixing of tuples and
1104                       records (e.g. #1).  It puts shorter names before longer so that
1105                       #11 comes after #2 and before #100.  For named records it does
1106                       not make for easy reading so we sort those alphabetically when
1107                       printing. *)
1108                    val sortedRecList =
1109                        Misc.quickSort(fn {name = a, ...} => fn {name = b, ...} => a <= b) recList
1110                in
1111                    PrettyBlock (2, false, [],
1112                        PrettyString "{" ::
1113                        (let
1114                            fun pRec [] _ = []
1115                              | pRec ({name, typeof} :: T) depth =
1116                                if depth <= 0 then [PrettyString "..."]
1117                                else
1118                                    [
1119                                    PrettyBlock(0, false, [],
1120                                        [
1121                                            PrettyBlock(0, false, [],
1122                                                [
1123                                                PrettyString (name ^ ":"),
1124                                                PrettyBreak(1, 0),
1125                                                dispP(typeof, depth - 1)
1126                                                ] @
1127                                                (if null T then [] else [PrettyBreak (0, 0), PrettyString ","])
1128                                            )
1129                                        ]@
1130                                        (if null T then [] else PrettyBreak (1, 0) :: pRec T (depth-1))
1131                                        )
1132                                    ]
1133                        in
1134                            pRec sortedRecList (depth - 1)
1135                        end) @
1136                        [ PrettyString (if recordIsFrozen r then "}" else case recList of [] =>   "...}" | _  => ", ...}")]
1137                        )
1138                end
1139
1140            |   OverloadSet {typeset = []} => PrettyString "no type"
1141
1142            |   OverloadSet {typeset = tconslist} =>
1143                (* This typically arises when printing error messages in the second pass because
1144                   the third pass will select a single type e.g. int where possible.  To
1145                   simplify the messages select a single type if possible. *)
1146                (
1147                    case preferredOverload tconslist of
1148                        SOME tcons => dispP(mkTypeConstruction (tcName tcons, tcons,[], []), depth)
1149                    |   NONE =>
1150                      (* Just print the type constructors separated by / *)
1151                    let
1152                        fun constrLocation tcons =
1153                            case List.find(fn DeclaredAt _ => true | _ => false) (tcLocations tcons) of
1154                                SOME(DeclaredAt loc) => [ContextLocation loc]
1155                            |   _ => []
1156                        (* Type constructor with context. *)
1157                        fun tconsItem tcons =
1158                            PrettyBlock(0, false, constrLocation tcons, [PrettyString(tcName tcons)])
1159
1160                        fun printTCcons [] = []
1161                          | printTCcons [tcons] = [tconsItem tcons]
1162                          | printTCcons (tcons::rest) =
1163                                tconsItem tcons :: PrettyBreak (0, 0) ::
1164                                PrettyString "/" :: printTCcons rest
1165                    in
1166                        PrettyBlock (0, false, [], printTCcons tconslist)
1167                    end
1168                )
1169
1170            |   EmptyType => PrettyString "no type"
1171            
1172            |   BadType => PrettyString "bad"
1173        end (* dispP *)
1174    in
1175        dispP (t, depth)
1176    end (* tDisp *);
1177
1178  (* Generate unique type-variable names. *)
1179
1180    fun varNameSequence () : typeVarForm -> string = 
1181    (* We need to ensure that every distinct type variable has a distinct name.
1182       Each new type variable is given a name starting at "'a" and going on
1183       through the alphabet. *)
1184    let
1185        datatype names = Names of {name: string, entry: typeVarForm}
1186        val nameNum    = ref ~1
1187        val gNameList  = ref [] (* List of names *)
1188    in
1189        (* If the type is already there return the name we have given it
1190           otherwise make a new name and put it in the list. *)
1191        fn var =>
1192            case List.find (fn (Names {entry,...}) => sameTv (entry, var)) (!gNameList) of
1193                NONE =>  (* Not on the list - make a new name *)
1194                let
1195                    fun name num = (if num >= 26 then name (num div 26 - 1) else "")
1196                          ^ String.str (Char.chr (num mod 26 + Char.ord #"a"))
1197                    val () = nameNum := !nameNum + 1
1198                    val n = (if tvEquality var then "''" else "'") ^ name(!nameNum)
1199                    (* Should explicit type variables be distinguished? *)
1200                in
1201                    gNameList := Names{name=n, entry=var} :: !gNameList;
1202                    n
1203                end
1204           |    SOME (Names {name,...}) => name
1205    end (* varNameSequence *)
1206
1207    (* Print a type (as a block of items) *)
1208    fun displayWithMap (t : types, depth : FixedInt.int, env, sigMap) =
1209        tDisp (t, depth, varNameSequence (), env, sigMap)
1210    and display (t : types, depth : FixedInt.int, env) =
1211        tDisp (t, depth, varNameSequence (), env, NONE)
1212
1213    (* Print out zero, one or more type variables (unblocked) *)
1214    fun printTypeVars([], _, _) = [] (* No type vars i.e. monotype *)
1215 
1216    |   printTypeVars([oneVar], depth, typeV) = (* Single type var. *)
1217        [
1218            tDisp (TypeVar oneVar, depth, typeV, emptyTypeEnv, NONE), 
1219            PrettyBreak (1, 0)
1220        ]
1221
1222    |   printTypeVars(vars, depth, typeV) =
1223        (* Must parenthesise them. *)
1224        if depth <= 1 then [PrettyString "..."]
1225        else
1226        [
1227            PrettyBlock(0, false, [],
1228                PrettyString "(" ::
1229                PrettyBreak(0, 0) ::
1230                (let
1231                    fun pVars vars depth: pretty list = 
1232                        if depth <= 0 then [PrettyString "..."]
1233                        else if null vars then []
1234                        else
1235                        [
1236                            tDisp (TypeVar(hd vars), depth, typeV, emptyTypeEnv, NONE),
1237                            PrettyBreak (0, 0)
1238                        ] @
1239                        (if null (tl vars) then []
1240                         else PrettyString "," :: PrettyBreak (1, 0) :: pVars (tl vars) (depth - 1)
1241                        )
1242                in
1243                    pVars vars depth
1244                end) @ [PrettyString ")"]
1245            ),
1246            PrettyBreak (1, 0)
1247        ]
1248  
1249  
1250    (* Version used in parsetree. *)
1251    fun displayTypeVariables (vars : typeVarForm list, depth : FixedInt.int) =
1252      printTypeVars (vars, depth, varNameSequence ())
1253    
1254 
1255    (* Parse tree for types.  This is used to represent types in the source. *)
1256    datatype typeParsetree =
1257        ParseTypeConstruction of
1258            { name: string, args: typeParsetree list,
1259              location: location, nameLoc: location, argLoc: location,
1260              (* foundConstructor is set to the constructor when it has been
1261                 looked up.  This allows us to get the location where it was
1262                 declared if we export the parse-tree. *)
1263              foundConstructor: typeConstrs ref }
1264    |   ParseTypeProduct of
1265            { fields: typeParsetree list, location: location }
1266    |   ParseTypeFunction of
1267            { argType: typeParsetree, resultType: typeParsetree, location: location }
1268    |   ParseTypeLabelled of
1269            { fields: ((string * location) * typeParsetree * location) list,
1270              frozen: bool, location: location }
1271    |   ParseTypeId of { types: typeVarForm, location: location }
1272    |   ParseTypeBad (* Place holder for errors. *)
1273
1274    fun typeFromTypeParse(
1275            ParseTypeConstruction{ args, name, location, foundConstructor = ref constr, ...}) =
1276        let
1277            val argTypes = List.map typeFromTypeParse args
1278        in
1279            TypeConstruction {name = name, constr = constr,
1280                              args = argTypes, locations = [DeclaredAt location]}
1281        end
1282
1283    |   typeFromTypeParse(ParseTypeProduct{ fields, ...}) =
1284            mkProductType(List.map typeFromTypeParse fields)
1285    
1286    |   typeFromTypeParse(ParseTypeFunction{ argType, resultType, ...}) =
1287            mkFunctionType(typeFromTypeParse argType, typeFromTypeParse resultType)
1288    
1289    |   typeFromTypeParse(ParseTypeLabelled{ fields, frozen, ...}) =
1290        let
1291            fun makeField((name, _), t, _) = mkLabelEntry(name, typeFromTypeParse t)        
1292        in
1293            mkLabelled(sortLabels(List.map makeField fields), frozen)
1294        end
1295    
1296    |   typeFromTypeParse(ParseTypeId{ types, ...}) = TypeVar types
1297    
1298    |   typeFromTypeParse(ParseTypeBad) = BadType
1299    
1300    fun makeParseTypeConstruction((constrName, nameLoc), (args, argLoc), location) =
1301        ParseTypeConstruction{
1302            name = constrName, nameLoc = nameLoc, args = args, argLoc = argLoc,
1303            location = location, foundConstructor = ref undefConstr }
1304
1305    fun makeParseTypeProduct(recList, location) =
1306        ParseTypeProduct{ fields = recList, location = location }
1307
1308    fun makeParseTypeFunction(arg, result, location) =
1309        ParseTypeFunction{ argType = arg, resultType = result, location = location }
1310
1311    fun makeParseTypeLabelled(recList, frozen, location) =
1312        ParseTypeLabelled{ fields = recList, frozen = frozen, location = location }
1313
1314    fun makeParseTypeId(types, location) =
1315        ParseTypeId{ types = types, location = location }
1316
1317    fun unitTree location = ParseTypeLabelled{ fields = [], frozen = true, location = location }
1318
1319    (* Build an export tree from the parse tree. *)
1320    fun typeExportTree(navigation, p: typeParsetree) =
1321    let        
1322        val typeof = typeFromTypeParse p
1323
1324        (* Common properties for navigation and printing. *)
1325        val commonProps =
1326            PTprint(fn d => display(typeof, d, emptyTypeEnv)) ::
1327            PTtype typeof ::
1328            exportNavigationProps navigation
1329
1330        fun asParent () = typeExportTree(navigation, p)
1331        
1332    in
1333        case p of
1334            ParseTypeConstruction{ location, nameLoc, args, argLoc, ...} =>
1335            let
1336                (* If the constructor has been bound return the declaration location.
1337                   We have to attach the declaration location in the right place if
1338                   this is a polytype e.g. if we have "int list" here we will have
1339                   the location for "list" which is the second item not the first. *)
1340                val (name, decLoc) =
1341                    case typeof of
1342                        TypeConstruction { constr, name, ...} =>
1343                            if isUndefined constr
1344                            then (name, [])
1345                            else (name, mapLocationProps(tcLocations constr))
1346                    |   _ => ("", []) (* Error? *)
1347                val navNameAndArgs =
1348                (* Separate cases for nullary, unary and higher type constructions. *)
1349                    case args of
1350                        [] => decLoc (* Singleton e.g. int *)
1351                    |   [oneArg] =>
1352                        let (* Single arg e.g. int list. *)
1353                            (* Navigate between the type constructor and the argument.
1354                               Since the arguments come before the constructor we go there first. *)
1355                            fun getArg () =
1356                                typeExportTree({parent=SOME asParent, previous=NONE, next=SOME getName}, oneArg)
1357                            and getName () =
1358                                getStringAsTree({parent=SOME asParent, previous=SOME getArg, next=NONE},
1359                                            name, nameLoc, decLoc)
1360                        in
1361                            [PTfirstChild getArg]
1362                        end
1363                    |   args =>
1364                        let (* Multiple arguments e.g. (int, string) pair *)
1365                            fun getArgs () =
1366                                (argLoc,
1367                                    exportList(typeExportTree, SOME getArgs) args @
1368                                        exportNavigationProps{parent=SOME asParent, previous=NONE, next=SOME getName})
1369                            and getName () =
1370                                getStringAsTree({parent=SOME asParent, previous=SOME getArgs, next=NONE},
1371                                            name, nameLoc, decLoc)
1372                        in
1373                            [PTfirstChild getArgs]
1374                        end
1375            in
1376                (location, navNameAndArgs @ commonProps)
1377            end
1378
1379        |   ParseTypeProduct{ location, fields, ...} =>
1380                (location, exportList(typeExportTree, SOME asParent) fields @ commonProps)
1381
1382        |   ParseTypeFunction{ location, argType, resultType, ...} =>
1383                (location, exportList(typeExportTree, SOME asParent) [argType, resultType] @ commonProps)
1384
1385        |   ParseTypeLabelled{ location, fields, ...} =>
1386            let
1387                fun exportField(navigation, label as ((name, nameLoc), t, fullLoc)) =
1388                    let
1389                        (* The first position is the label, the second the type *)
1390                        fun asParent () = exportField (navigation, label)
1391                        fun getLab () =
1392                            getStringAsTree({parent=SOME asParent, next=SOME getType, previous=NONE},
1393                                name, nameLoc, [PTtype(typeFromTypeParse t)])
1394                        and getType () =
1395                            typeExportTree({parent=SOME asParent, previous=SOME getLab, next=NONE}, t)
1396                    in
1397                        (fullLoc, PTfirstChild getLab :: exportNavigationProps navigation)
1398                    end
1399            in
1400                (location, exportList(exportField, SOME asParent) fields @ commonProps)
1401            end
1402
1403        |   ParseTypeId{ location, ...} =>
1404                (location, commonProps)
1405
1406        |   ParseTypeBad =>
1407                (nullLocation, commonProps)
1408    end
1409
1410    fun displayTypeParse(types, depth, env) = display(typeFromTypeParse types, depth, env)
1411
1412    (* Associates type constructors from the environment with type identifiers
1413       (NOT type variables) *)
1414    fun assignTypes (tp : typeParsetree,  lookupType : string * location -> typeConstrSet, lex : lexan) =
1415    let
1416        fun typeFromTypeParse(ParseTypeConstruction{ args, name, location, foundConstructor, ...}) =
1417            let
1418                (* Assign constructor, then the parameters. *)
1419                val TypeConstrSet(constructor, _) = lookupType (name, location)
1420                val () =
1421                    (* Check that it has the correct arity. *)
1422                    if not (isUndefined constructor)
1423                    then
1424                    let
1425                        val arity : int = tcArity constructor;
1426                        val num   : int = length args;
1427                    in
1428                        if arity <> num
1429                        then (* Give an error message *)
1430                        errorMessage (lex, location,
1431                            String.concat["Type constructor (", tcName constructor,
1432                                ") requires ", Int.toString arity, " type(s) not ",
1433                                Int.toString num])
1434                        else foundConstructor := constructor
1435                    end
1436                    else ()
1437                val argTypes = List.map typeFromTypeParse args
1438            in
1439                TypeConstruction {name = name, constr = constructor,
1440                                  args = argTypes, locations = [DeclaredAt location]}
1441            end
1442
1443        |   typeFromTypeParse(ParseTypeProduct{ fields, ...}) =
1444                mkProductType(List.map typeFromTypeParse fields)
1445    
1446        |   typeFromTypeParse(ParseTypeFunction{ argType, resultType, ...}) =
1447                mkFunctionType(typeFromTypeParse argType, typeFromTypeParse resultType)
1448    
1449        |   typeFromTypeParse(ParseTypeLabelled{ fields, frozen, ...}) =
1450            let
1451                fun makeField((name, _), t, _) = mkLabelEntry(name, typeFromTypeParse t)        
1452            in
1453                mkLabelled(sortLabels(List.map makeField fields), frozen)
1454            end
1455    
1456        |   typeFromTypeParse(ParseTypeId{ types, ...}) = TypeVar types
1457    
1458        |   typeFromTypeParse(ParseTypeBad) = BadType
1459    in
1460        typeFromTypeParse tp
1461    end;
1462
1463    (* When we have finished processing a list of patterns we need to check
1464       that the record is now frozen. *)
1465    fun recordNotFrozen (TypeVar t) : bool = (* Follow the chain *) recordNotFrozen (tvValue t)
1466    |   recordNotFrozen (LabelledType r) = not(recordIsFrozen r)
1467    |   recordNotFrozen _ = false (* record or type alias *);
1468
1469    datatype generalMatch = Matched of {old: typeVarForm, new: types};
1470
1471    fun generaliseTypes (atyp : types, checkTv: typeVarForm->types option) = 
1472    let
1473        val madeList = ref [] (* List of tyVars. *);
1474
1475        fun tvs atyp =
1476        let
1477            val tyVar = typesTypeVar atyp;
1478        in
1479            case List.find(fn Matched{old, ...} => sameTv (old, tyVar)) (!madeList) of
1480                SOME(Matched{new, ...}) => new
1481            |   NONE =>
1482                (
1483                case checkTv tyVar of
1484                    SOME found => found
1485                |   NONE =>
1486                    let  (* Not on the list - make a new name *)
1487                        (* Make a unifiable type variable even if the original
1488                           is nonunifiable. *)
1489                        val n : types = 
1490                            mkTypeVar (generalisable, tvEquality tyVar, false, tvPrintity tyVar)
1491                    in
1492                        (* Set the new variable to have the same value as the
1493                           existing.  That is only really needed if we have an
1494                           overload set. *)
1495                        tvSetValue (typesTypeVar n, tvValue tyVar);
1496                        madeList := Matched {old = tyVar, new = n} :: !madeList;
1497                        n
1498                    end
1499                )
1500        end
1501
1502        fun copyTypeVar (atyp as TypeVar tyVar) =
1503            if tvLevel tyVar <> generalisable
1504            then atyp (* Not generalisable. *)
1505            else (* Unbound, overload set or flexible record *)
1506            let
1507                val newTv = tvs atyp
1508            in
1509                (* If we have a type variable pointing to a flexible record we have to
1510                   copy the type pointed at by the variable. *)
1511                case tvValue tyVar of
1512                    valu as LabelledType _ =>
1513                        tvSetValue (typesTypeVar newTv, copyType (valu, copyTypeVar, fn t => t))
1514                |   _ => ();
1515                newTv
1516            end
1517        | copyTypeVar atyp = atyp
1518        
1519        val copied =
1520            (* Only process type variables. Return type constructors unchanged. *)
1521            copyType (atyp, copyTypeVar, fn t => t (*copyTCons*))
1522    in
1523        (copied, ! madeList)
1524    end (* generaliseTypes *);
1525
1526    (* Exported wrapper for generaliseTypes. *)
1527    fun generalise atyp =
1528    let
1529        val (t, newMatch) = generaliseTypes (atyp, fn _ => NONE)
1530        fun makeResult(Matched{new, old}) =
1531            {value=new, equality=tvEquality old, printity=tvPrintity old}
1532    in
1533        (t, List.map makeResult newMatch)
1534    end;
1535
1536    (* Return the original polymorphic type variables. *)
1537    fun getPolyTypeVars(atyp, map) =
1538    let
1539        val (_, newMatch) = generaliseTypes (atyp, map)
1540    in
1541        List.map (fn(Matched{old, ...}) => old) newMatch
1542    end;
1543    
1544    fun generaliseWithMap(atyp, map) =
1545    let
1546        val (t, newMatch) = generaliseTypes (atyp, map)
1547        fun makeResult(Matched{new, old}) =
1548            {value=new, equality=tvEquality old, printity=tvPrintity old}
1549    in
1550        (t, List.map makeResult newMatch)
1551    end
1552  
1553   (* Find the argument type which gives this result when the constructor
1554      is applied. If we have, for example, a value of type int list and
1555      we have discovered that this is a "::" node we have to work back by
1556      comparing the type of "::" ('a * 'a list -> 'a list) to find the
1557      argument of the constructor (int * int list) and hence how to print it.
1558     (Actually "list" is treated specially). *)
1559    fun constructorResult (FunctionType{arg, result=TypeConstruction{args, ...}}, typeArgs) =
1560        let
1561            val matches = ListPair.zip(List.map typesTypeVar args, typeArgs)
1562            fun getArg tv =
1563                case List.find(fn (atv, _) => sameTv(tv, atv)) matches of
1564                    SOME (_, ty) => SOME ty
1565                |   NONE => NONE
1566        in
1567            #1 (generaliseTypes(arg, getArg))
1568        end
1569    | constructorResult _ = raise InternalError "Not a function type"
1570
1571    (* If we have a type construction which is an alias for another type
1572       we construct the alias by first instantiating all the type variables
1573       and then copying the type. *)
1574    fun makeEquivalent (atyp, args) =
1575        case tcIdentifier atyp of
1576            TypeId{idKind=TypeFn(typeArgs, typeResult), ...} =>
1577            let
1578                val matches = ListPair.zip(typeArgs, args)
1579                fun getArg tv =
1580                    case List.find(fn (atv, _) => sameTv(tv, atv)) matches of
1581                        SOME (_, ty) => SOME ty
1582                    |   NONE => NONE
1583            in
1584                #1 (generaliseTypes(typeResult, getArg))
1585            end
1586
1587        |   TypeId _ => raise InternalError "makeEquivalent: Not a type function"
1588
1589    (* Look for the occurrence of locally declared datatypes in the type of a value. *)
1590    fun checkForEscapingDatatypes(ty: types, errorFn: string->unit) : unit =
1591    let
1592        fun checkTypes (typ: types) (ok: bool) : bool =
1593        case typ of
1594            TypeConstruction {constr, args, ...} =>
1595                if tcIsAbbreviation constr
1596                then (* May be an alias for a type that contains a local datatype. *)
1597                    foldType checkTypes (makeEquivalent (constr, args)) ok
1598                else if ok
1599                then
1600                (
1601                    case tcIdentifier constr of
1602                        TypeId{access=Local{addr, ...}, ...} =>
1603                            if !addr < 0
1604                            then 
1605                            (
1606                                errorFn("Type of expression contains local datatype (" ^ tcName constr
1607                                        ^") outside its definition.");
1608                                false
1609                            )
1610                            else true
1611                    |   _ => true (* Could we have a "selected" entry with a local datatype? *)
1612                )
1613                else false
1614        |   _ => ok
1615    in
1616        foldType checkTypes ty true;
1617        ()
1618    end
1619
1620  (* This 3-valued logic is used because in a few cases we may not be sure
1621     if equality testing is allowed. If we have 2 mutually recursive datatypes
1622     t = x of s | ... and s = z of t we would first examine "t", find that
1623     it uses "s", look at "s", find that refers back to "t". To avoid
1624     infinite recursion we return the result that equality "maybe"
1625     allowed for "t" and hence for "s". However we may find that the
1626     other constructors for "t" do not allow equality and so equality
1627     will not be allowed for "s" either. *)
1628     
1629  datatype tri = Yes (* 3-valued logic *)
1630               | No
1631               | Maybe;
1632
1633
1634  (* Returns a flag saying if equality testing is allowed for values of
1635     the given type. "equality" is used both to generate the code for
1636     a specific call of equality e.g.  (a, b, c) = f(x), and to generate
1637     the equality operation for a type when it is declared. In the latter
1638     case type variables may be parameters which will be filled in later e.g.
1639     type 'a list = nil | op :: of ('a * 'a list). "search"
1640     is a function which looks up constructors in mutually recursive type
1641     declarations. "lookupTypeVar" deals with type variables. If they
1642     represent parameters to a type declaration equality 
1643     checking will be allowed. If we are unifying this type to an equality
1644     type variable they  will be unified to new equality type variables.
1645     Otherwise equality is not allowed. *)
1646    
1647    fun equality (ty, search, lookupTypeVar) : tri =
1648    let
1649        (* Can't use foldT because it is not monotonic
1650           (equality on ref 'a is allowed). *)
1651        (* Returns Yes only if equality testing is allowed for all types
1652           in the list. *)
1653        fun eqForList ([],    soFar) = soFar
1654          | eqForList (x::xs, soFar) = 
1655            case equality (x, search, lookupTypeVar) of
1656               No    => No
1657             | Maybe => eqForList (xs, Maybe)
1658             | Yes   => eqForList (xs, soFar);
1659    in
1660        case eventual ty of
1661            TypeVar tyVar => (* The type variable may point to a flexible record or
1662                          an overload set or it may be the end of the chain.
1663                          If this is a labelled record we have to make sure that
1664                          any fields we add also admit equality.
1665                          lookupTypeVar makes the type variable an equality type
1666                          so that any new fields are checked for equality but
1667                          we also have to call "equality" to check the existing
1668                          fields. *)
1669                if tvEquality tyVar then Yes
1670                else
1671                    (
1672                    case tvValue tyVar of
1673                        lab as LabelledType _ =>
1674                            (
1675                            case lookupTypeVar tyVar of
1676                                No => No
1677                              | _ => equality (lab, search, lookupTypeVar)
1678                            )
1679                     | _ => lookupTypeVar tyVar
1680                    )
1681   
1682        |   FunctionType {...} => No  (* No equality on function types! *)
1683    
1684        |   TypeConstruction {constr, args, ...} =>
1685            if isUndefined constr
1686            then No
1687
1688            else if tcIsAbbreviation constr
1689            then (* May be an alias for a type that allows equality. *)
1690                equality (makeEquivalent (constr, args), search, lookupTypeVar)
1691
1692            (* ref - Equality is permitted on refs of all types *)
1693            (* The Definition of Standard ML says that ref is the ONLY type
1694               constructor which is treated in this way.  The standard basis
1695               library says that other mutable types such as array should
1696               also work this way. *)
1697            else if isPointerEqType(tcIdentifier constr)
1698            then Yes
1699
1700            (* Others apart from ref and real *)
1701            else if tcEquality constr (* Equality allowed. *)
1702            then eqForList (args, Yes) (* Must be allowed for all the args *)
1703      
1704            else
1705            let (* Not an alias. - Look it up. *)
1706                val s = search (tcIdentifier constr);
1707            in 
1708                if s = No then No else eqForList (args, s)
1709            end (* TypeConstruction *)
1710         
1711        |   LabelledType {recList, ...} => (* Record equality if all subtypes are (ignore frozen!) *)
1712                (* TODO: Avoid copying the list? *)
1713                eqForList (map (fn{typeof, ...}=>typeof) recList, Yes)
1714
1715        |   OverloadSet _ =>
1716                (* This should not happen because all overload sets should be pointed
1717                   to by type variables and so should be handled in the TypeVar case. *)
1718                raise InternalError "equality - Overloadset found"
1719
1720        |   BadType => No
1721
1722        |   EmptyType => No (* shouldn't occur *)
1723    end
1724
1725  (* When a datatype is declared we test to see if equality is allowed. The
1726     types are mutually recursive so value constructors of one type may
1727     take arguments involving values of any of the others. *)
1728     
1729    fun computeDatatypeEqualities(types: typeConstrSet list, boundIdEq) =
1730    let
1731        datatype state =
1732          Processed of tri              (* Already processed or processing. *)
1733        | NotSeen   of typeConstrSet list (* Value is list of constrs. *);
1734    
1735        (* This table tells us, for each type constructor, whether it definitely
1736           admits equality, definitely does not or whether we have yet to look
1737           at it. *)
1738
1739        fun isProcessed (Processed _) = true | isProcessed _ = false;
1740    
1741        fun stateProcessed (Processed x) = x | stateProcessed _ = raise Match;
1742        fun stateNotSeen   (NotSeen   x) = x | stateNotSeen   _ = raise Match;
1743    
1744        val {enter:typeId * state -> unit,lookup} = mapTable sameTypeId;
1745
1746        (* Look at each of the constructors in the list. Equality testing is
1747           only allowed if it is allowed for each of the alternatives. *)
1748        fun constrEq _           []       soFar = soFar (* end of list - all o.k. *)
1749        |   constrEq constructor (h :: t) soFar =
1750            (* The constructor may be a constant e.g.
1751               datatype 'a list = nil | ... or  a function e.g.
1752               datatype 'a list = ... cons of 'a * 'a list. *)
1753            if not (isFunctionType (valTypeOf h)) (* Constant *)
1754            then constrEq constructor t soFar (* Go on to the next. *)
1755      
1756            else
1757            let
1758                (* Function - look at the argument type. *)
1759                (* Equality is allowed for any type-variable.  The only type variables
1760                   allowed are parameters to the datatype so if we have a type variable
1761                   then equality is allowed for this datatype.  *)
1762                val eq = 
1763                    equality (#arg (typesFunctionType (valTypeOf h)),
1764                        genEquality, fn _ => Yes);
1765            in
1766                if eq = No
1767                then (* Not allowed. *) No
1768                else (* O.k. - go on to the next. *)
1769                    constrEq constructor t (if eq = Maybe then Maybe else soFar)
1770            end (* constrEq *)
1771
1772        (* This procedure checks to see if equality is allowed for this datatype. *)
1773        and genEquality constructorId =
1774        let 
1775            (* Look it up to see if we have already done it. It may fail because
1776               we may have constructors that do not admit equality. *)
1777            val thisState =
1778                case (lookup constructorId, constructorId) of
1779                    (SOME inList, _) => inList
1780                |   (NONE, TypeId{idKind = Bound{offset, ...}, ...}) =>
1781                        Processed(if boundIdEq offset then Yes else No)
1782                |   _ => Processed No
1783        in
1784            if isProcessed thisState
1785            then stateProcessed thisState (* Have either done it already or are currently doing it. *)
1786            else (* notSeen - look at it now. *)
1787            let
1788                (* Equality is allowed for this datatype only if all of them admit it.
1789                   There are various other alternatives but this is what the standard says.
1790                   If the "name" is rigid (free) we must not grant equality if it is not 
1791                   already there although that is not an error. *)
1792                (* Set the state to "Maybe". This prevents infinite recursion. *)
1793                val () = enter (constructorId, Processed Maybe);
1794                val eq =
1795                    List.foldl 
1796                        (fn (cons, t) => 
1797                        if t = No
1798                        then No
1799                        else constrEq cons (tsConstructors cons) t)
1800                        Yes
1801                        (stateNotSeen thisState);
1802            in
1803                (* Set the state we have found if it is "yes" or "no".  If it is
1804                   maybe we have a recursive reference which appears to admit
1805                   equality, but may not. E.g. if we have
1806                             datatype t = A of s | B of int->int  and  s = C of t
1807                   if we start processing "t" we will go on to "s" and do that
1808                   before returning to "t". It is only later we find that "t" does
1809                   not admit equality. If we get "Maybe" as the final result when
1810                   all the recursion has been unwound we can set the result to
1811                   "yes", but any intermediate "Maybe"s have to be done again. *)
1812                enter (constructorId, if eq = Maybe then thisState else Processed eq);
1813                eq
1814            end
1815        end (* genEquality *);
1816    in
1817        (* If we have an eqtype we set it to true, otherwise we set all of them
1818           to "notSeen" with the constructor as value. *)
1819        List.app 
1820            (fn dec as TypeConstrSet(decCons, _) => 
1821            let  (* If we have two datatypes which share we may already have
1822                    one in the table.  We have to link them together. *)
1823                val tclist =
1824                    case lookup (tcIdentifier decCons) of
1825                        NONE => [dec]
1826                    |   SOME l =>
1827                        let
1828                            val others = stateNotSeen l
1829                            val newList = dec :: others;
1830                        in
1831                            (* If any of these are already equality types (i.e. share with an eqtype)
1832                               then they all must be. *)
1833                            if tcEquality decCons orelse tcEquality (tsConstr(hd others))
1834                            then List.app (fn d => tcSetEquality (tsConstr d, true)) newList
1835                            else ();
1836                            newList
1837                        end
1838            in
1839                enter (tcIdentifier decCons, NotSeen tclist)
1840            end) types;
1841
1842        (* Apply genEquality to each element of the list. *)
1843        List.app
1844            (fn TypeConstrSet(constructor, _) => 
1845            let
1846                val constructorId = tcIdentifier constructor;
1847                val eqForCons     = genEquality constructorId;
1848            in
1849                (* If the result is "Maybe" it involves a recursive reference, but
1850                   the rest of the type allows equality. The type admits equality. *)
1851                if eqForCons = No
1852                then () (* Equality not allowed *)
1853                else
1854                ( (* Turn on equality. *)
1855                    enter (constructorId, Processed Yes);
1856                    tcSetEquality (constructor, true)
1857                )
1858            end) types
1859    end (* computeDatatypeEqualities *);
1860    
1861    datatype matchResult =
1862        SimpleError of types * types * string
1863    |   TypeConstructorError of types * types * typeConstrs * typeConstrs
1864
1865    (* Type matching algorithm for both unification and signature matching. *)
1866    (* The mapping has now been moved out of here.  Instead when signature matching the
1867       target signature is copied before this is called which means that this
1868       process is now symmetric.  There may be some redundant tests left in here. *)
1869    fun unifyTypes(Atype : types, Btype : types) : matchResult option =
1870    let
1871        (* Get the result in here.  This isn't very ML-like but it greatly
1872           simplifies converting the code. *)
1873        val matchResult: matchResult option ref = ref NONE
1874        fun matchError error = (* Only report one error. *)
1875            case matchResult of ref (SOME _) => () | r => r := SOME error
1876        fun cantMatch(alpha, beta, text) = matchError(SimpleError(alpha, beta, text))
1877  
1878        fun match (Atype : types, Btype : types) : unit =
1879        let (* Check two records/tuples and return the combined type. *)
1880            fun unifyRecords (rA as {recList=typAlist, fullList = gA},
1881                              rB as {recList=typBlist, fullList = gB},
1882                              typA : types, typB : types) : types =
1883            let        
1884                val typAFrozen = recordIsFrozen rA
1885                and typBFrozen = recordIsFrozen rB
1886
1887                fun matchLabelled ([], []) = []
1888          
1889                     (* Something left in bList - this is fine if typeA is not frozen.
1890                        e.g.  (a: s, b: t) will match (a: s, ...) but not just (a:s). *)
1891                |   matchLabelled ([], bList as {name=bName, ...} :: _) =
1892                    ( 
1893                        if typAFrozen
1894                        then cantMatch (typA, typB, "(Field " ^ bName ^ " missing)")
1895                        else ();
1896                        bList (* return the remainder of the list *)
1897                    )
1898
1899                |   matchLabelled (aList as {name=aName, ...} :: _, []) = (* Something left in bList *)
1900                    ( 
1901                        if typBFrozen
1902                        then cantMatch (typA, typB, "(Field " ^ aName ^ " missing)")
1903                        else ();
1904                        aList (* the rest of aList *)
1905                    )
1906        
1907                |   matchLabelled (aList as ((aVal as {name=aName,typeof=aType})::aRest),
1908                                   bList as ((bVal as {name=bName,typeof=bType})::bRest)) =
1909                    (* both not nil - look at the names. *)
1910                    let
1911                        val order = compareLabels (aName, bName);
1912                    in
1913                        if order = 0 (* equal *)
1914                        then (* same name - must be unifiable types *)
1915                        ( (* The result is (either) one of these with the rest of the list. *)
1916                            match (aType, bType);
1917                            aVal :: matchLabelled (aRest, bRest)
1918                        )
1919                        else if order < 0 (* aName < bName *)
1920                        then (* The entries in each list are in order so this means that this
1921                               entry is not in bList. If the typeB is frozen this is an error. *)
1922                            if typBFrozen (* Continue with the entry removed. *)
1923                        then (cantMatch (typA, typB, "(Field " ^ aName ^ " missing)"); aList)
1924                        else aVal :: matchLabelled (aRest, bList)
1925                        else (* aName > bName *)
1926                            if typAFrozen
1927                        then (cantMatch (typA, typB, "(Field " ^ bName ^ " missing)"); bList)
1928                        else bVal :: matchLabelled (aList, bRest)
1929                     end (* not nil *);
1930 
1931                (* Return the combined list. Only actually used if both are flexible. *)
1932                val result =
1933                    if typAFrozen andalso typBFrozen andalso List.length typAlist <> List.length typBlist
1934                    then (* Don't attempt to unify the fields if we have the wrong number of items.
1935                            If we've added or removed an item from a tuple e.g. a function with
1936                            multiple arguments, it's more useful to know this than to get unification
1937                            errors on fields that don't match. *)
1938                        (cantMatch (typA, typB, "(Different number of fields)"); [])
1939                    else matchLabelled (typAlist, typBlist)
1940
1941                fun lastFlex(FlexibleList(ref(r as FlexibleList _))) = lastFlex r
1942                |   lastFlex(FlexibleList r) = SOME r
1943                |   lastFlex(FieldList _) = NONE
1944
1945            in
1946                if typAFrozen
1947                then (if typBFrozen then () else valOf(lastFlex gB) := gA; typA)
1948                else if typBFrozen
1949                then (valOf(lastFlex gA) := gB; typB)
1950                else
1951                let
1952                    (* We may have these linked already in which case we shouldn't do anything. *)
1953                    val lastA = valOf(lastFlex gA) and lastB = valOf(lastFlex gB)
1954                in
1955                    if lastA = lastB
1956                    then ()
1957                    else
1958                    let
1959                        val genericFields = FieldList(map #name result, false)
1960                    in
1961                        (* If these are both flexible we have link all the generics together
1962                           so that if we freeze any one of them they all get frozen. *)
1963                        lastA := genericFields;
1964                        lastB := FlexibleList lastA
1965                    end;
1966                    LabelledType {recList = result, fullList = gA}
1967                end
1968            end (* unifyRecords *);
1969
1970            (* Sets a type variable to a value. - Checks that the type variable
1971               we are assigning does not occur in the expression we are about to
1972               assign to it. Such cases can occur if we have infinitely-typed
1973               expressions such as fun a. a::a where a has type 'a list list ...
1974               Also propagates the level information of the type variable.
1975               Now also deals with flexible records. *)
1976            fun assign (var, t) =
1977            let
1978              (* Mapped over the type to be assigned. *)
1979              (* Returns "false" if it is safe to make the assignment. Sorts out
1980                 imperative type variables and propagates level information.
1981                 N.B. It does not propagate equality status. The reason is that
1982                 if we are unifying ''a with 'b ref, the 'b does NOT become
1983                 an equality type var. In all other cases it would. *)
1984                fun occursCheckFails _ true = true
1985
1986                |   occursCheckFails ty false =
1987                    let
1988                        val t = eventual ty
1989                    in
1990                        case t of
1991                            TypeVar tvar =>
1992                            let
1993                                (* The level is the minimum of the two, and if we are unifying with
1994                                   an equality type variable we must make this into one. *)
1995                                val minLev = Int.min (tvLevel var, tvLevel tvar)
1996                                val oldValue = tvValue tvar
1997                            in
1998                                if tvLevel tvar <> minLev
1999                                then (* If it is nonunifiable we cannot make its level larger. *)
2000                                    if tvNonUnifiable tvar
2001                                then cantMatch (Atype, Btype, "(Type variable is free in surrounding scope)")
2002                                else
2003                                let
2004                                    (* Must make a new type var with the right properties *)
2005                                    (* This type variable may be a flexible record, in which
2006                                       case we have to save the record and put it on the new
2007                                       type variable.  We have to do this for the record itself so that new
2008                                       fields inherit the correct status and also for any existing fields. *)
2009                                    val newTv = mkTypeVar (minLev, tvEquality tvar, false, tvPrintity tvar)
2010                                in
2011                                    tvSetValue (typesTypeVar newTv, oldValue);
2012                                    tvSetValue (tvar, newTv)
2013                                end
2014                                else ();
2015                                (* Safe if vars are different but we also have to check any flexible records. *)
2016                                occursCheckFails oldValue (sameTv (tvar, var))
2017                            end
2018
2019                        |   TypeConstruction {args, constr, ...} =>
2020                                (* If this is a type abbreviation we have to expand this before processing
2021                                   any arguments.  We mustn't process arguments that are not actually used. *)
2022                                if tcIsAbbreviation constr
2023                                then occursCheckFails(makeEquivalent (constr, args)) false
2024                                else List.foldr (fn (t, v) => occursCheckFails t v) false args
2025
2026                        |   FunctionType {arg, result} =>
2027                                occursCheckFails arg false orelse occursCheckFails result false
2028
2029                        |   LabelledType {recList,...} =>
2030                                List.foldr (fn ({ typeof, ... }, v) => occursCheckFails typeof v) false recList
2031
2032                        |   _ => false
2033
2034                    end
2035
2036                val varVal = tvValue var (* Current value of the variable to be set. *)
2037
2038                local
2039                    (* We need to process any type abbreviations before applying the occurs check.
2040                       The type we're assigning could boil down to the same type variable we're
2041                       trying to assign.  This doesn't breach the occurs check. *)
2042                    fun followVarsAndTypeFunctions t =
2043                    case eventual t of
2044                        ev as TypeConstruction{constr, args, ...} =>
2045                        if tcIsAbbreviation constr
2046                        then followVarsAndTypeFunctions(makeEquivalent (constr, args))
2047                        else ev
2048                    |   ev => ev
2049                in
2050                    val finalType = followVarsAndTypeFunctions t
2051                end
2052      
2053              (* We may actually have the same type variable after any type abbreviations
2054                 have been followed. *)
2055              val reallyTheSame =
2056                    case finalType of
2057                        TypeVar tv => sameTv (tv, var)
2058                    |   _ => false
2059
2060            in (* start of "assign" *)
2061                case varVal of
2062                    LabelledType _ =>
2063                    (* Flexible record. Check that the records are compatible. *)
2064                        match (varVal, t)
2065                |   OverloadSet _ =>
2066                     (* OverloadSet.  Check that the sets match.  This is only in the
2067                        case where t is something other than an overload set since
2068                        we remove the overload set from a variable when unifying two
2069                        sets. *)
2070                        match (varVal, t)
2071                |   _ => ();
2072 
2073                if reallyTheSame
2074                then () (* Don't apply the occurs check or check for non-unifiable. *)
2075
2076                (* If this type variable was put in explicitly then it can't be
2077                   assigned to something else. (We have already checked for the
2078                   type variables being the same). *)
2079                else if tvNonUnifiable var
2080                then cantMatch (Atype, Btype, "(Cannot unify with explicit type variable)")
2081
2082                else if occursCheckFails finalType false
2083                then cantMatch (Atype, Btype, "(Type variable to be unified occurs in type)")
2084
2085                else
2086                let (* Occurs check succeeded. *)
2087                    fun canMkEqTv (tvar : typeVarForm) : tri = 
2088                    (* Turn it into an equality type var. *)
2089                    if tvEquality tvar then Yes 
2090                    (* If it is nonunifiable we cannot make it into an equality type var. *)
2091                    else if tvNonUnifiable tvar then No
2092                    else (* Must make a new type var with the right properties *)
2093                    let  (* This type variable may be a flexible record or an overload set,
2094                            in which case we have to save the record and put it on the
2095                            new type variable.
2096                            We have to do both because we have to ensure that the existing
2097                            fields in the flexible record admit equality and ALSO that any
2098                            additional fields we may add by unification with other records
2099                            also admit equality. *)
2100                        val newTv = mkTypeVar (tvLevel tvar, true, false, tvPrintity tvar)
2101                        val oldValue = tvValue tvar
2102                    in
2103                        tvSetValue (tvar, newTv);
2104                        (* If this is an overloaded type we must remove any types that
2105                           don't admit equality. *)
2106                        case oldValue of
2107                            OverloadSet{typeset} =>
2108                            let
2109                            (* Remove any types which do not admit equality. *)
2110                               fun filter [] = []
2111                                |  filter (h::t) =
2112                                        if tcEquality h then h :: filter t else filter t
2113                            in
2114                                case filter typeset of
2115                                    [] => No
2116                                |   [constr] =>
2117                                    ( (* Turn a singleton into a type construction. *)
2118                                        tvSetValue (typesTypeVar newTv,
2119                                            mkTypeConstruction(tcName constr, constr, nil, []));
2120                                        Yes
2121                                    )
2122                                |   newset =>
2123                                    (
2124                                        tvSetValue (typesTypeVar newTv, OverloadSet{typeset=newset});
2125                                        Yes
2126                                    )
2127                            end
2128                        |   _ => (* Labelled record or unbound variable. *)
2129                            (
2130                                tvSetValue (typesTypeVar newTv, oldValue);
2131                                Yes
2132                            )
2133                    end
2134      
2135                in
2136                    (* If we are unifying a type with an equality type variable
2137                       we must ensure that equality is allowed for that type. This
2138                       will turn most type variables into equality type vars. *)
2139                    if tvEquality var andalso equality (t, fn _ => No, canMkEqTv) = No
2140                    then cantMatch (Atype, Btype, "(Requires equality type)")
2141                      (* TODO: This can result in an unhelpful message if var is bound
2142                         to a flexible record since there is no indication in the
2143                         printed type that the flexible record is an equality type.
2144                         It would be improved if we set the value to be EmptyType.
2145                         At least then the type variable would be printed which would
2146                         be an equality type.
2147                         --- Adding the "Requires equality type" should improve things. *)
2148                    else ();
2149                    (* Propagate the "printity" status.  This is probably not complete
2150                       but doesn't matter too much since this is a Poly extension. *)
2151                    if tvPrintity var
2152                    then
2153                    let
2154                        fun makePrintity(TypeVar tv) _ =
2155                        (
2156                            if tvPrintity tv then ()
2157                            else case tvValue tv of
2158                                (* If it's an overload set we don't need to do anything. This will
2159                                   eventually be a monotype. *)
2160                                OverloadSet _ => ()
2161                            |   oldValue =>
2162                                let (* Labelled record or unbound variable. *)
2163                                    val newTv = mkTypeVar (tvLevel tv, tvEquality tv, tvNonUnifiable tv, true)
2164                                in
2165                                    tvSetValue(tv, newTv);
2166                                    (* Put this on the chain if it's a labelled record. *)
2167                                    tvSetValue (typesTypeVar newTv, oldValue)
2168                                end
2169                        )
2170
2171                        |   makePrintity _ _ = ()
2172                    in
2173                        foldType makePrintity t ()
2174                    end
2175                    else ();
2176                    (* Actually make the assignment. It doesn't matter if var is 
2177                       a labelled record, because t will be either a fixed record
2178                       or a combination of the fields of var and t.  Likewise if
2179                       var was previously an overload set this may replace the set
2180                       by a single type construction. *)
2181                    (* If we have had an error don't make the assignment.  At the very least
2182                       it could prevent us producing useful error information and it could
2183                       also result in unnecessary consequential errors. *)
2184                    case !matchResult of
2185                        NONE => tvSetValue (var, t)
2186                    |   SOME _ => ()
2187                end
2188            end (* assign *);
2189
2190            (* First find see if typeA and typeB are unified to anything
2191               already, and get the end of a list of "flexibles".  *)
2192
2193            val tA = eventual Atype
2194            and tB = eventual Btype
2195
2196        in (* start of "match" *)
2197            if isUndefinedType tA orelse isUndefinedType tB
2198            then () (* If either of these was an undefined type constructor don't try to match. 
2199                       TODO: There are further tests below for this which are now redundant. *)
2200            else
2201            case (tA, tB) of
2202                (BadType, _) => () (* If either is an error don't try to match *)
2203            |   (_, BadType) => ()
2204
2205            |   (TypeVar typeAVar, TypeVar typeBVar) =>
2206                (* Unbound type variable, flexible record or overload set. *)
2207                let
2208                    (* Even if this is a one-way match we can allow type variables
2209                       in the typeA to be instantiated to anything in the typeB. *)
2210                    val typeAVal = tvValue typeAVar;
2211                    (* We have two unbound type variables or flex. records. *)
2212                in
2213                    if sameTv (typeAVar, typeBVar) (* same type variable? *)
2214                    then ()
2215                    else (* no - assign one to the other *)
2216                        if tvNonUnifiable typeAVar
2217                        (* If we have a nonunifiable type variable we want to assign
2218                           the typeB to  it. If the typeB is nonunifiable as well we
2219                           will get an error message. *)
2220                    then assign (typeBVar, tA)
2221                    else
2222                    let 
2223                        (* If they are both flexible records we first set the typeB
2224                           to the union of the records, and then set the typeA to
2225                           that. In that way we propagate properties such as
2226                           equality and level between the two variables. *)
2227                        val typBVal = tvValue typeBVar
2228                    in
2229                        case (typeAVal, typBVal) of
2230                            (LabelledType recA, LabelledType recB) =>
2231                            (
2232                                (* Turn these back into simple type variables to save
2233                                 checking the combined record against the originals
2234                                 when we make the assignment.
2235                                 (Would be safe but redundant). *)
2236                                tvSetValue (typeBVar, emptyType);
2237                                tvSetValue (typeAVar, emptyType);
2238                                assign (typeBVar,
2239                                      unifyRecords (recA, recB, typeAVal, typBVal));
2240                                assign (typeAVar, tB)
2241                            )
2242                        |   (OverloadSet{typeset=setA}, OverloadSet{typeset=setB}) =>
2243                            let
2244                                (* The lists aren't ordered so we just have to go
2245                                   through by hand. *)
2246                                fun intersect(_, []) = []
2247                                |   intersect(a, H::T) =
2248                                        if isInSet(H, a) then H::intersect(a, T) else intersect(a, T)
2249                                val newSet = intersect(setA, setB)
2250                            in
2251                                case newSet of
2252                                    [] => cantMatch (Atype, Btype, "(Incompatible overloadings)")
2253                                |   _ =>
2254                                    (
2255                                        tvSetValue (typeBVar, emptyType);
2256                                        tvSetValue (typeAVar, emptyType);
2257                                        (* I've changed this from OverloadSet{typeset=newset}
2258                                         to use mkOverloadSet.  The main reason was that it
2259                                         fixed a bug which resulted from a violation of the
2260                                         assumption that "equality" would not be passed an
2261                                         overload set except when pointed to by a type variable.
2262                                         It also removed the need for a separate test for
2263                                         singleton sets since mkOverloadSet deals with them.
2264                                         DCJM 1/9/00. *)
2265                                        assign (typeBVar, mkOverloadSet newSet);
2266                                        assign (typeAVar, tB)
2267                                    )
2268                            end
2269                        |   (EmptyType, _) => (* A is not a record or an overload set. *)
2270                                assign (typeAVar, tB)
2271                        |   (_, EmptyType) => (* A is a record but B isn't *)
2272                                assign (typeBVar, tA) (* typeB is ordinary type var. *)
2273                        |   _ => (* Bad combination of labelled record and overload set *)
2274                                cantMatch (Atype, Btype, "(Incompatible types)")
2275                    end
2276                end
2277
2278            |   (TypeVar typeAVar, _) =>
2279                    (* typeB is not a type variable so set typeA to typeB.*)
2280                    (* Be careful if this is a non-unifiable type variable being matched to
2281                       the special case of the identity type-construction. *)
2282                (
2283                    if tvNonUnifiable typeAVar orelse (case tvValue typeAVar of OverloadSet _ => true | _ => false)
2284                    then
2285                        (
2286                        case tB of
2287                            TypeConstruction {constr, args, ...} =>
2288                                if isUndefined constr orelse not (tcIsAbbreviation constr)
2289                                then
2290                                    (
2291                                    case tB of
2292                                        TypeConstruction {constr, args, ...} =>
2293                                            if isUndefined constr orelse not (tcIsAbbreviation constr)
2294                                            then assign (typeAVar, tB)
2295                                            else match(tA, eventual (makeEquivalent (constr, args)))
2296                                    | _ => assign (typeAVar, tB)
2297                                    )
2298                                else match(tA, eventual (makeEquivalent (constr, args)))
2299
2300                        |  _ => assign (typeAVar, tB)
2301                        )
2302                    else assign (typeAVar, tB)
2303                )
2304     
2305            |   (_, TypeVar typeBVar) => (* and typeA is not *)
2306                (
2307                    (* We have to check for the special case of the identity type-construction. *)
2308                    if tvNonUnifiable typeBVar orelse (case tvValue typeBVar of OverloadSet _ => true | _ => false)
2309                    then
2310                        (
2311                        case tA of
2312                            TypeConstruction {constr, args, ...} =>
2313                                if isUndefined constr orelse not (tcIsAbbreviation constr)
2314                                then
2315                                    (
2316                                    case tB of
2317                                        TypeVar tv =>
2318                                          (* This will fail if we are matching a signature because the
2319                                             typeB will be non-unifiable. *)
2320                                            assign (tv, tA) (* set typeB to typeA *)
2321                                      | typB => match (tA, typB)
2322                                    )
2323                                else match(eventual (makeEquivalent (constr, args)), tB)
2324                        |  _ =>
2325                            (
2326                            case tB of
2327                                TypeVar tv =>
2328                                  (* This will fail if we are matching a signature because the
2329                                     typeB will be non-unifiable. *)
2330                                    assign (tv, tA) (* set typeB to typeA *)
2331                              | typB => match (tA, typB)
2332                            )
2333                        )
2334                    else
2335                        (
2336                        case tB of
2337                            TypeVar tv =>
2338                              (* This will fail if we are matching a signature because the
2339                                 typeB will be non-unifiable. *)
2340                                assign (tv, tA) (* set typeB to typeA *)
2341                          | typB => match (tA, typB)
2342                        )
2343                )
2344          
2345            |   (TypeConstruction({constr = tACons, args=tAargs, ...}), 
2346                 TypeConstruction ({constr = tBCons, args=tBargs, ...})) =>
2347                (
2348                    (* We may have a number of possibilities here.
2349                     a) If tA is an alias we simply expand it out and recurse (even
2350                     if tB is the same alias). e.g. if we have string t where
2351                     type 'a t = int*'a we expand string t into int*string and
2352                     try to unify that.
2353                     b) map it and see if the result is an alias. -- NOW REMOVED
2354                     c) If tB is a type construction and it is an alias we expand
2355                     that e.g. unifying "int list" and "int t" where type
2356                     'a t = 'a list (particularly common in signature/structure
2357                     matching.)
2358                     d) Finally we try to unify the stamps and the arguments. *)
2359                    if isUndefined tACons orelse isUndefined tBCons
2360                    then () (* If we've had an undefined type constructor don't try to check further. *)
2361                    else if tcIsAbbreviation tACons
2362                    (* Candidate is an alias - expand it. *)
2363                    then match (makeEquivalent (tACons, tAargs), tB)
2364                    else if tcIsAbbreviation tBCons
2365                    then match (tA, makeEquivalent (tBCons, tBargs))
2366                    else if tcIsAbbreviation tBCons (* If the typeB is an alias it must be expanded. *)
2367                    then match (tA, makeEquivalent (tBCons, tBargs))
2368                    else if sameTypeId (tcIdentifier tACons, tcIdentifier tBCons)
2369                    then
2370                    let (* Same type constructor - do the arguments match? *)
2371                        fun matchLists []      []    = ()
2372                          | matchLists (a::al) (b::bl) =
2373                          (  
2374                            match (a, b);
2375                            matchLists al bl
2376                          )
2377                          | matchLists _ _ = (* This should only happen as a result of
2378                                                a different error. *)
2379                                cantMatch (Atype, Btype, "(Different numbers of arguments)")
2380                    in
2381                            matchLists tAargs tBargs
2382                    end
2383
2384                    (* When we have different type constructors, especially two with the same name,
2385                       we try to produce more information. *)
2386                    else matchError(TypeConstructorError(tA, tB, tACons, tBCons))
2387                )
2388
2389            |   (OverloadSet {typeset}, TypeConstruction {constr=tBCons, args=tBargs, ...}) =>
2390                (* The candidate is an overloaded type and the target is a type
2391                   construction. *)
2392                (
2393                    if not (isUndefined tBCons orelse not (tcIsAbbreviation tBCons))
2394                    then match (tA, makeEquivalent (tBCons, tBargs))
2395                    else if isUndefined tBCons
2396                    then ()
2397                    else if tcIsAbbreviation tBCons
2398                    then match (tA, makeEquivalent (tBCons, tBargs))
2399                    else (* See if the target type is among those in the overload set. *)
2400                        if null tBargs (* Must be a nullary type constructor. *)
2401                            andalso isInSet(tBCons, typeset)
2402                    then () (* ok. *)
2403                        (* Overload sets arise primarily with literals such as "1" and it's
2404                           most likely that the error is a mismatch between int and another
2405                           type rather than that the user assumed that the literal was
2406                           overloaded on a type it actually wasn't. *)
2407                    else
2408                    case preferredOverload typeset of
2409                        NONE => cantMatch (tA, tB, "(Different type constructors)")
2410                    |   SOME prefType =>
2411                        matchError(
2412                            TypeConstructorError(
2413                                mkTypeConstruction (tcName prefType, prefType,[], []),
2414                                tB, prefType, tBCons))
2415                )
2416
2417            |   (TypeConstruction {constr=tACons, args=tAargs, ...}, OverloadSet {typeset}) =>
2418                (
2419                    if not (isUndefined tACons orelse not (tcIsAbbreviation tACons))
2420                    then match (makeEquivalent (tACons, tAargs), tB)
2421                    (* We should never find an overload set as the target for a signature
2422                       match but it is perfectly possible for tB to be an overload set
2423                       when unifying two types.  *)
2424                    else if null tAargs andalso isInSet(tACons, typeset)
2425                    then () (* ok. *)
2426                    else
2427                    case preferredOverload typeset of
2428                        NONE => cantMatch (tA, tB, "(Different type constructors)")
2429                    |   SOME prefType =>
2430                        matchError(
2431                            TypeConstructorError(
2432                                tA, mkTypeConstruction (tcName prefType, prefType,[], []),
2433                                tACons, prefType))
2434                )
2435
2436            |   (OverloadSet _ , OverloadSet _) => raise InternalError "Unification: OverloadSet/OverloadSet"
2437                (* (OverloadSet , OverloadSet) should not occur because that should be
2438                 handled in the (TypeVar, TypeVar) case. *)
2439    
2440            |   (TypeConstruction({constr = tACons, args=tAargs, ...}), _) =>
2441                    if not (isUndefined tACons orelse not (tcIsAbbreviation tACons))
2442                    (* Candidate is an alias - expand it. *)
2443                    then match (makeEquivalent (tACons, tAargs), tB)
2444                    else (* typB not a construction (but typeA is) *)
2445                        cantMatch (tA, tB, "(Incompatible types)")
2446    
2447            |   (_, TypeConstruction {constr=tBCons, args=tBargs, ...}) => (* and typeA is not. *)
2448                    (* May have a type equivalence e.g. "string t" matches int*string if  type
2449                       'a t = int * 'a . Alternatively we may be matching a structure to a signature
2450                       where the signature says "type t" and the structure contains "type 
2451                       t = int->int" (say). We need to set the type in the signature to int->int. *)
2452                    if not (isUndefined tBCons orelse not (tcIsAbbreviation tBCons))
2453                    then match (tA, makeEquivalent (tBCons, tBargs))
2454                    else if isUndefined tBCons
2455                    then ()
2456                    else if tcIsAbbreviation tBCons
2457                    then match (tA, makeEquivalent (tBCons, tBargs))
2458                    else cantMatch (tB, tA, "(Incompatible types)")
2459
2460     
2461            |   (FunctionType {arg=typAarg, result=typAres, ...},
2462                 FunctionType {arg=typBarg, result=typBres, ...}) =>
2463                ( (* must be unifiable functions *)
2464                    (* In principle it doesn't matter whether we unify arguments or
2465                       results first but it could affect the error messages.  Is this
2466                       the best way to do it? *)
2467                    match (typAarg, typBarg);
2468                    match (typAres, typBres)
2469                )
2470
2471            |   (EmptyType, EmptyType) => ()
2472                    (* This occurs only with exceptions - empty means no argument *)
2473
2474            |   (LabelledType recA, LabelledType recB) =>
2475                    (* Unify the records, but discard the result because at least one of the
2476                     records is frozen. *)
2477                    (unifyRecords (recA, recB, tA, tB); ())
2478        
2479            |   _ => cantMatch (tA, tB, "(Incompatible types)")
2480
2481        end (* match *)
2482
2483    in
2484        match (Atype, Btype);
2485        ! matchResult
2486    end (* unifyTypes *)
2487
2488    (* Turn a result from matchTypes into a pretty structure so that it
2489       can be included in a message. *)
2490    fun unifyTypesErrorReport (_, alphaTypeEnv, betaTypeEnv, what) =
2491    let
2492        fun reportError(SimpleError(alpha: types, beta: types, reason)) =
2493            (* This previously used a single type variable sequence for
2494               both types.  It may be that this is needed to make
2495               sensible error messages. *)
2496            PrettyBlock(3, false, [],
2497                [
2498                    PrettyString ("Can't " ^ what (* "match" if a signature, "unify" if core lang. *)),
2499                    PrettyBreak (1, 0),
2500                    display (alpha, 1000 (* As deep as necessary *), alphaTypeEnv),
2501                    PrettyBreak (1, 0),
2502                    PrettyString "to",
2503                    PrettyBreak (1, 0),
2504                    display (beta, 1000 (* As deep as necessary *), betaTypeEnv),
2505                    PrettyBreak (1, 0),
2506                    PrettyString reason                        
2507                ])
2508
2509        |   reportError(TypeConstructorError(alpha: types, beta: types, alphaCons, betaCons)) =
2510            let
2511                fun expandedTypeConstr(ty, tyEnv, tyCons) =
2512                let
2513                    fun lastPart name = #second(splitString name)
2514
2515                    (* Print the type which includes the type constructor name with as
2516                       much additional information as we can. *)
2517                    fun printWithDesc{ location, name, description } =
2518                        PrettyBlock(3, false, [],
2519                            [ display (ty, 1000, tyEnv) ]
2520                            @ (if lastPart name = lastPart(tcName tyCons) then []
2521                               else
2522                                [
2523                                    PrettyBreak(1, 0),
2524                                    PrettyString "=",
2525                                    PrettyBreak(1, 0),
2526                                    PrettyBlock(0, false, [ContextLocation location], [PrettyString name])
2527                                ]
2528                              )
2529                            @ (if description = "" then []
2530                               else
2531                                [
2532                                    PrettyBreak(1, 0),
2533                                    PrettyBlock(0, false, [ContextLocation location],
2534                                        [PrettyString ("(*" ^ description ^ "*)")])
2535                                ]
2536                              )
2537                            )
2538                in
2539                    case tcIdentifier tyCons of
2540                        TypeId { description, ...} => printWithDesc description
2541                end
2542            in
2543                PrettyBlock(3, false, [],
2544                    [
2545                        PrettyString ("Can't " ^ what (* "match" if a signature, "unify" if core lang. *)),
2546                        PrettyBreak (1, 0),
2547                        expandedTypeConstr(alpha, alphaTypeEnv, alphaCons),
2548                        PrettyBreak (1, 0),
2549                        PrettyString (if what = "unify" then "with" else "to"),
2550                        PrettyBreak (1, 0),
2551                        expandedTypeConstr(beta, betaTypeEnv, betaCons),
2552                        PrettyBreak (1, 0),
2553                        PrettyString "(Different type constructors)"                        
2554                    ])
2555            end
2556            
2557    in
2558        reportError
2559    end
2560
2561  (* Given a function type returns the first argument if the
2562     function takes a tuple otherwise returns the only argument.
2563     Extended to include the case where the argument is not a function
2564     in order to work properly for overloaded literals. *)
2565  fun firstArg(FunctionType{arg=
2566        LabelledType { recList = {typeof, ...} ::_, ...}, ...}) =
2567            eventual typeof
2568   |  firstArg(FunctionType{arg, ...}) = eventual arg
2569   |  firstArg t = t
2570
2571    (* Returns an instance of an overloaded function using the supplied
2572       list of type constructors for the overloading. *)
2573    fun generaliseOverload(t, constrs, isConverter) =
2574    let
2575        (* Returns the result type of a function. *)
2576        fun getResult(FunctionType{result, ...}) = eventual result
2577        |   getResult _ = raise InternalError "getResult - not a function";
2578
2579        val arg = if isConverter then getResult t else firstArg t
2580    in
2581        case arg of
2582            TypeVar tv =>
2583            let
2584                (* The argument should be a type variable, possibly set to
2585                   an empty overload set.  This should be replaced by
2586                   the current overload set in the copied function type. *)
2587                val newSet = mkOverloadSet constrs
2588                val (t, _) = generaliseTypes(t, fn old => if sameTv(old, tv) then SOME newSet else NONE)
2589            in
2590                (t, [newSet])
2591            end
2592          | _ => raise InternalError "generaliseOverload - arg is not a type var"
2593    end
2594    (* Prints out a type constructor e.g. type 'a fred = 'a * 'a
2595       or datatype 'a joe = bill of 'a list | mary of 'a * int or
2596       simply type 'a abs if the type is abstract. *)
2597    fun displayTypeConstrsWithMap (
2598        TypeConstrSet(
2599            TypeConstrs{identifier=TypeId{idKind=TypeFn(args, result), ...}, name, ...}, []), depth, typeEnv, sigMap) =
2600         (* Type function *)
2601        if depth <= 0 
2602        then PrettyString "..."
2603        else
2604        let
2605            val typeV = varNameSequence () (* Local sequence for this binding. *)
2606        in
2607            PrettyBlock (3, false, [],
2608                PrettyString "type" ::
2609                PrettyBreak (1, 0) ::
2610                printTypeVars (args, depth, typeV) @
2611                [
2612                    PrettyString (#second(splitString name)),
2613                    PrettyBreak(1, 0),
2614                    PrettyString "=",
2615                    PrettyBreak(1, 0),
2616                    tDisp(result, depth-1, typeV, typeEnv, sigMap)
2617                ]
2618                )
2619        end
2620
2621    |   displayTypeConstrsWithMap (TypeConstrSet(tCons, [] (* No constructors *)), depth, _, _) =
2622        (* Abstract type or type in a signature. *)
2623        if depth <= 0 
2624        then PrettyString "..."
2625        else PrettyBlock (3, false, [],
2626            PrettyString (
2627                if tcEquality tCons then "eqtype" else "type") ::
2628            PrettyBreak (1, 0) ::
2629            printTypeVars (tcTypeVars tCons, depth, varNameSequence ()) @
2630            [PrettyString (#second(splitString(tcName tCons)))]
2631            )
2632
2633    |   displayTypeConstrsWithMap (TypeConstrSet(tCons as TypeConstrs{name, locations, ...}, tcConstructors), depth, typeEnv, sigMap) =
2634            (* It has constructors - datatype declaration *)
2635        if depth <= 0 
2636        then PrettyString "..."
2637        else
2638        let
2639            val typeV = varNameSequence ()
2640            (* Construct a ('a, 'b, 'c) tyCons construction for the result types
2641               of each of the constructors.  N.B. We use the original type
2642               constructors because they have the appropriate equality type properties.
2643               datatype 'a t = A of 'a is not the same as ''a t = A of ''a. *)
2644            val typeVars = tcTypeVars tCons
2645            val typeResult = mkTypeConstruction(name, tCons, map TypeVar typeVars, locations)
2646
2647            (* Print a single constructor (blocked) *)
2648            fun pValConstr (first, name, typeOf, depth) =
2649            let
2650                val (t, _) = generalise typeOf
2651                val firstBreak = PrettyBreak (1, if first then 2 else 0)
2652            in
2653                case t of
2654                    FunctionType { arg, result} =>
2655                    let
2656                        (* Constructor with an argument.  The constructor "type" is the argument.
2657                           We have to unify the result type of the function with the
2658                           ('a, 'b, 'c) tyCons type so that we get the correct type variables
2659                           in the argument.  We just print the argument of the function. *)
2660                        val _ = unifyTypes(result, typeResult)
2661                    in
2662                        [
2663                            firstBreak,
2664                            PrettyBlock (0, false, [],
2665                                PrettyBlock (0, false, [],
2666                                (if first then PrettyBreak (0, 2)
2667                                 else PrettyBlock (0, false, [], [PrettyString "|", PrettyBreak(1, 2)]) 
2668                                 ) ::
2669                                 (if depth <= 0 then [PrettyString "..."]
2670                                 else [ PrettyString name, PrettyBreak (1, 4), PrettyString "of"])
2671                            ) ::
2672                            (if depth > 0
2673                            then
2674                            [
2675                                PrettyBreak (1, 4),
2676                                (* print the type as a single block of output *)
2677                                tDisp (arg, depth - 1, typeV, typeEnv, sigMap)
2678                            ]
2679                            else [])
2680                            )
2681                        ]
2682                    end
2683
2684                |   _ =>
2685                    [
2686                        firstBreak,
2687                        PrettyBlock (0, false, [],
2688                            [if first then PrettyBreak (0, 2)
2689                            else PrettyBlock (0, false, [], [PrettyString "|", PrettyBreak(1, 2)]),
2690                            PrettyString (if depth <= 0 then "..." else name)]
2691                        )
2692                    ]
2693            end
2694          
2695            (* Print a sequence of constructors (unblocked) *)
2696            fun pValConstrRest ([],     _    ): pretty list = []
2697            |   pValConstrRest (H :: T, depth): pretty list =
2698                if depth < 0 then []           
2699                else pValConstr (false, valName H, valTypeOf H, depth) @
2700                        pValConstrRest (T, depth - 1)
2701           
2702            fun pValConstrList ([],     _    ) = PrettyString "" (* shouldn't occur *)    
2703            |   pValConstrList (H :: T, depth) =
2704                    PrettyBlock (2, true, [],
2705                        pValConstr (true, valName H, valTypeOf H, depth) @
2706                        pValConstrRest (T, depth - 1)
2707                    )
2708
2709            in
2710                PrettyBlock(0, false, [],
2711                    [
2712                        PrettyBlock(0, false, [],
2713                                PrettyString "datatype" ::
2714                                PrettyBreak (1, 2) ::
2715                                printTypeVars (typeVars, depth, typeV) @
2716                                [ PrettyString(#second(splitString(tcName tCons))), PrettyBreak(1, 0), PrettyString "=" ]
2717                        ),
2718                        pValConstrList (tcConstructors, depth - 1)
2719                    ]
2720                )
2721            end (* displayTypeConstrsWithMap *)
2722
2723    fun displayTypeConstrs (tCons : typeConstrSet, depth : FixedInt.int, typeEnv) : pretty =
2724        displayTypeConstrsWithMap(tCons, depth, typeEnv, NONE)
2725
2726    (* Return a type constructor from an overload.  If there are
2727       several (i.e. the overloading has not resolved to a single type)
2728       it returns the "best".  This is called in the third pass so it
2729       should never be called if there is not at least one type that
2730       is possible. *)
2731    fun typeConstrFromOverload(f, _) =
2732    let
2733    fun prefType(TypeVar tvar) =
2734            ( (* If we still have an overload set that's because it has
2735                 not reduced to a single type.  In ML 97 we default to
2736                 int, real, word, char or string in that order.  This
2737                 works correctly for overloading literals so long as
2738                 the literal conversion functions are correctly installed. *)
2739            case tvValue tvar of
2740                OverloadSet{typeset} =>
2741                    let
2742                        (* If we accept this type we have to freeze the
2743                            overloading to this type.
2744                            I'm not happy about doing this here but it
2745                            seems the easiest solution. *)
2746                        fun freezeType tcons =
2747                            (
2748                            tvSetValue(tvar,
2749                                mkTypeConstruction(tcName tcons, tcons, [], []));
2750                            tcons
2751                            )
2752                    in
2753                        case preferredOverload typeset of
2754                            SOME tycons => freezeType tycons
2755                        |   NONE => raise InternalError "typeConstrFromOverload: No matching type"
2756                    end
2757              | _ => raise InternalError "typeConstrFromOverload: No matching type" (* Unbound or flexible record. *)
2758            )
2759     |  prefType(TypeConstruction{constr, args, ...}) =
2760            if not (tcIsAbbreviation constr)
2761            then constr (* Generally args will be nil in this case but
2762                           in the special case of looking for an equality
2763                           function for 'a ref or 'a array it may not be.  *)
2764            else prefType (makeEquivalent (constr, args))
2765     |  prefType _ = raise InternalError "typeConstrFromOverload: No matching type"
2766    in
2767        prefType(firstArg(eventual f))
2768    end;
2769
2770    (* Return the result type of a function.  Also used to test if the value is
2771       a function type. *)
2772    fun getFnArgType t =
2773    case eventual t of
2774        FunctionType {arg, ... } => SOME arg
2775    |   _ => NONE
2776    
2777
2778  (* Assigns type variables to variables with generalisation permitted
2779     if their level is at least that of the current level.
2780     In ML90 mode this produced an error message for any top-level
2781     free imperative type variables.  We don't do that in ML97 because
2782     it is possible that another declaration may "freeze" the type variable
2783     before the composite expression reaches the top level. *)
2784  fun allowGeneralisation (t, level, nonExpansive, lex, location, moreInfo, typeEnv) =
2785    let
2786        fun giveError(s1: string, s2: string) =
2787        let
2788            (* Use a single sequence. *)
2789            val vars : typeVarForm -> string = varNameSequence ();
2790            open DEBUG
2791            val parameters = debugParams lex
2792            val errorDepth = getParameter errorDepthTag parameters
2793        in
2794            reportError lex
2795            {
2796                hard = true,
2797                location = location,
2798                message =
2799                    PrettyBlock (3, false, [],
2800                        [
2801                            PrettyString s1,
2802                            PrettyBreak (1, 0),
2803                            tDisp (t, errorDepth, vars, typeEnv, NONE),
2804                            PrettyBreak (1, 0),
2805                            PrettyString s2
2806                        ]
2807                    ),
2808                context = SOME(moreInfo ())
2809            }
2810        end
2811
2812        local
2813            open DEBUG
2814            val parameters = debugParams lex
2815        in
2816            val checkOverloadFlex = getParameter narrowOverloadFlexRecordTag parameters
2817        end
2818
2819        fun general t (genArgs as (showError, nonExpansive)) =
2820            case eventual t of
2821                TypeVar tvar =>
2822                let
2823                    val argSet =
2824                        if tvLevel tvar >= level andalso tvLevel tvar <> generalisable
2825                            andalso (case tvValue tvar of OverloadSet _ => false | _ => true)
2826                        then
2827                        let
2828                            (* Make a new generisable type variable, except that type
2829                               variables in an expansive context cannot be generalised.
2830                               We also don't generalise if this is an overload set.
2831                               The reason for that is that it allows us to get overloading
2832                               information from the surrounding context.
2833                               e.g. let fun f x y = x+y in f 2.0 end.  An alternative
2834                               would be take the default type (in this case int).
2835                               DCJM 1/9/00. *)
2836                            val nonCopiable = not nonExpansive
2837                            val newLevel =
2838                               if nonCopiable then level-1 else generalisable (* copiable *);
2839
2840                            val isOk =
2841                                (* If the type variable has top-level scope then we have
2842                                   a free type variable.  We only want to generate this
2843                                   message once even if we have multiple type variables.*)
2844                                (* If the type variable is non-unifiable and the expression is
2845                                   expansive then we have an error since this will have to
2846                                   be a monotype.  *)
2847                                if tvNonUnifiable tvar andalso nonCopiable andalso showError
2848                                then
2849                                    (
2850                                    giveError("Type", "includes a free type variable");
2851                                    false
2852                                    )
2853                                else showError;
2854                            (* It may be a flexible record so we have to transfer the
2855                               record to the new variable. *)
2856                            val newTypeVar =
2857                                makeTv {value=tvValue tvar, level=newLevel, equality=tvEquality tvar,
2858                                        nonunifiable=if nonCopiable then (tvNonUnifiable tvar) else false,
2859                                        printable=tvPrintity tvar}
2860                        in
2861                            tvSetValue (tvar, TypeVar newTypeVar);
2862                            (* If we are using the "narrow" context for overloading and
2863                               flexible records we should apply this here.  Otherwise it is
2864                               dealt with in the next pass when we have the full program context. *)
2865                            case (checkOverloadFlex, tvValue tvar) of
2866                                (true, LabelledType _) => giveError("Type", "is an unresolved flexible record")
2867                            |   (true, OverloadSet {typeset, ...}) =>
2868                                (   (* Set this to the "preferred" type.  Typically this is "int" but for overloaded literals
2869                                       (e.g. 0w0) it could be something else. *)
2870                                    case preferredOverload typeset of
2871                                        SOME tycons =>
2872                                            tvSetValue(tvar,
2873                                                mkTypeConstruction(tcName tycons, tycons, [], []))
2874                                    |   NONE => raise InternalError "general: No matching type"
2875                                )
2876                            |   _ => ();
2877                            (isOk, nonExpansive)
2878                        end
2879                        else genArgs
2880                in
2881                    general (tvValue tvar) argSet (* Process any flexible record. *)
2882                end
2883           
2884            |   TypeConstruction {args, constr, ...} =>
2885                    (* There is a pathological case here.  If we have a type equivalence
2886                       which contains type variables that do not occur on the RHS
2887                       (e.g. type 'a t = int) then we generalise over them even with an
2888                       expansive expression.  This is because the semantics treats type
2889                       abbreviations as type functions and so any type variables that
2890                       are eliminated by the function application do not appear in the
2891                       "type" that the semantics applies to the expression. *)
2892                    if tcIsAbbreviation constr
2893                    then
2894                    let
2895                        val (r1, _) = general(makeEquivalent (constr, args)) genArgs
2896                        (* Process any arguments that have not been processed in the equivalent. *)
2897                        val (r2, _) = List.foldr (fn (t, v) => general t v) (r1, true) args
2898                    in
2899                        (r2, nonExpansive)
2900                    end
2901                    else List.foldr (fn (t, v) => general t v) genArgs args
2902
2903            |   FunctionType {arg, result} => general arg (general result genArgs)
2904
2905            |   LabelledType {recList,...} =>
2906                    List.foldr (fn ({ typeof, ... }, v) => general typeof v) genArgs recList
2907
2908            |   _ => genArgs
2909    in
2910        general t (true, nonExpansive);
2911        ()
2912    end (*  end allowGeneralisation *);
2913
2914  (* Check for free type variables at the top level.  Added for ML97.  This replaces the
2915     test in allowGeneralisation above and is applied to all top-level
2916     values including those in structures and functors.  *)
2917  (* I've changed this from giving an error message, which prevented the
2918     code from evaluating, to giving a warning and setting the type
2919     variables to unique type variables.  That allows, for example,
2920     fun f x = raise x; f Subscript; to work.  DCJM 8/3/01. *)
2921  fun checkForFreeTypeVariables(valName: string, ty: types, lex: lexan, printAndEqCode) : unit =
2922  let
2923    (* Generate new names for the type constructors. *)
2924    val count = ref 0
2925    fun genName num =
2926        (if num >= 26 then genName (num div 26 - 1) else "")
2927        ^ String.str (Char.chr (num mod 26 + Char.ord #"a"));
2928
2929    fun checkTypes (TypeVar tvar) () =
2930        if isEmpty(tvValue tvar) andalso tvLevel tvar = 1
2931        then (* The type variable is unbound (specifically, not
2932                an overload set) and it is not generic i.e. it
2933                must have come from an expansive expression. *)
2934            let
2935                val name = "_" ^ genName(!count)
2936                val _ = count := !count + 1;
2937                val declLoc = location lex (* Not correct but OK for the moment. *)
2938                val declDescription =
2939                    { location = declLoc, name = name, description = "Constructed from a free type variable." }
2940                val tCons =
2941                    makeTypeConstructor (name, [],
2942                        makeFreeId(0, Global(printAndEqCode()), tvEquality tvar, declDescription),
2943                        [DeclaredAt declLoc]);
2944                val newVal = mkTypeConstruction(name, tCons, [], [])
2945            in
2946                warningMessage(lex, location lex, 
2947                    concat["The type of (", valName,
2948                        ") contains a free type variable. Setting it to a unique monotype."]);
2949                tvSetValue (tvar, newVal)
2950            end
2951        else ()
2952     |  checkTypes _ () = ()
2953
2954  in
2955      foldType checkTypes ty ();
2956    ()
2957  end
2958
2959    (* Returns true if a type constructor permits equality. *)
2960    
2961    fun permitsEquality constr =
2962        if tcIsAbbreviation constr
2963        then typePermitsEquality(
2964                mkTypeConstruction (tcName constr, constr, List.map TypeVar (tcTypeVars constr), []))
2965        else tcEquality constr
2966   
2967    and typePermitsEquality ty = equality (ty, fn _ => No, fn _ => Yes) <> No
2968
2969    (* See if a type abbreviation or "where type" has the form type t = s or
2970       type 'a t = 'a s etc and so is simply giving a new name to the type
2971       constructor.  If it is it then checks that the type constructor used
2972       (s in this example) is just a simple type name. *)
2973    fun typeNameRebinding(typeArgs, typeResult): typeId option =
2974    let
2975        fun eqTypeVar(TypeVar ta, tb) = sameTv (ta, tb)
2976        |   eqTypeVar _ = false
2977    in
2978        case typeResult of
2979            TypeConstruction {constr, args, ... } =>
2980                if not (ListPair.allEq eqTypeVar(args, typeArgs))
2981                then NONE
2982                else
2983                (
2984                    case tcIdentifier constr of
2985                        TypeId{idKind=TypeFn _, ...} => NONE
2986                    |   tId => SOME tId
2987
2988                )
2989        |   _ => NONE
2990    end
2991
2992  (* Returns the number of the entry in the list. Used to find out the
2993     location of fields in a labelled record for expressions and pattern
2994     matching. Assumes that the label appears in the list somewhere. *)
2995     
2996  fun entryNumber (label, LabelledType{recList, ...}) =
2997    let (* Count up the list. *)
2998      fun entry ({name, ...}::l) n =
2999        if name = label then n else entry l (n + 1)
3000       |  entry [] _ = raise Match
3001    in
3002      entry recList 0
3003    end
3004      
3005   | entryNumber (label, TypeVar tvar) =
3006        entryNumber (label, tvValue tvar)
3007      
3008   | entryNumber (label, TypeConstruction{constr, ...}) = (* Type alias *)
3009        entryNumber (label, tcEquivalent constr)
3010      
3011   | entryNumber _ =
3012        raise InternalError "entryNumber - not a record"
3013
3014  (* Size of a labelled record. *)
3015
3016  fun recordWidth (LabelledType{recList, ...}) =
3017        length recList
3018      
3019   | recordWidth (TypeVar tvar) =
3020        recordWidth (tvValue tvar)
3021      
3022   | recordWidth (TypeConstruction{constr, ...}) = (* Type alias *)
3023        recordWidth (tcEquivalent constr)
3024      
3025   | recordWidth _ =
3026        raise InternalError "entryNumber - not a record"
3027
3028    fun recordFieldMap f (LabelledType{recList, ...}) = List.map (f o (fn {typeof, ...} => typeof)) recList
3029    |   recordFieldMap f (TypeVar tvar) = recordFieldMap f (tvValue tvar)
3030    |   recordFieldMap f (TypeConstruction{constr, ...}) = recordFieldMap f (tcEquivalent constr)
3031    |   recordFieldMap _ _ = raise InternalError "entryNumber - not a record"
3032
3033    (* Unify two type variables which would otherwise be non-unifiable.
3034       Used when we have found a local type variable with the same name
3035       as a global one. *)
3036    fun linkTypeVars (a, b) =
3037    let
3038        val ta = typesTypeVar (eventual(TypeVar a)); (* Must both be type vars. *)
3039        val tb = typesTypeVar (eventual(TypeVar b));
3040    in  (* Set the one with the higher level to point to the one with the
3041         lower, so that the effective level is the lower. *)
3042        if (tvLevel ta) > (tvLevel tb)
3043        then tvSetValue (ta, TypeVar b)
3044        else tvSetValue (tb, TypeVar a)
3045    end;
3046
3047    (* Set its level by setting it to a new type variable. *)
3048    fun setTvarLevel (typ, level) =
3049    let
3050        val tv = typesTypeVar (eventual(TypeVar typ)); (* Must be type var. *)
3051    in
3052        tvSetValue (tv, mkTypeVar (level, tvEquality tv, true, tvPrintity tv))
3053    end;
3054
3055    (* Construct the least general type from a list of types.  This is used after
3056       type checking to try to remove polymorphism from local values.  It takes
3057       the list of actual uses of the value, usually a function, and removes
3058       any unnecessary polymorphism.  This is particularly the case if the
3059       function involves a flexible record, where the unspecified fields are
3060       treated as polymorphic, but where the function is actually applied
3061       to a records which are monomorphic. *)
3062    fun leastGeneral [] = EmptyType (* Never used? *)
3063
3064    (* Don't use this at the moment - see the comment on TypeVar below.
3065       Also the comment on TypeConstruction for local datatypes. *)
3066(*    |   leastGeneral [oneType] = oneType *)(* Just one - this is it. *)
3067
3068    |   leastGeneral(firstType::otherTypes): types =
3069    let
3070        fun canonical (typ as TypeVar tyVar) =
3071            (
3072                case tvValue tyVar of
3073                    EmptyType => typ
3074                |   OverloadSet _ =>
3075                    let
3076                        val constr = typeConstrFromOverload(typ, false)
3077                    in
3078                        mkTypeConstruction(tcName constr, constr, [], [])
3079                    end
3080                |   t => canonical t
3081            )
3082        |   canonical (typ as TypeConstruction { constr, args, ...}) =
3083                if tcIsAbbreviation constr (* Handle type abbreviations directly *)
3084                then canonical(makeEquivalent (constr, args))
3085                else typ
3086        |   canonical typ = typ
3087
3088        (* Take the head of the each argument list and extract the least general.
3089           Then process the tail.  It's an error if each element of the list
3090           does not contain the same number of items. *)
3091        fun leastArgs ([]::_) = []
3092        |   leastArgs (args as _::_) =
3093                leastGeneral(List.map hd args) :: leastArgs (List.map tl args)
3094        |   leastArgs _ = raise Empty
3095
3096    in
3097        case canonical firstType of
3098            (*typ as *)TypeVar _(*tv*) =>
3099            let
3100                (*fun sameTypeVar(TypeVar tv1) = sameTv(tv, tv1) | sameTypeVar _ = false*)
3101            in
3102                (* If they are all the same type variable return that otherwise return
3103                   a new generalisable type variable.  They may all be equal if we always
3104                   apply this function to a value whose type is a polymorphic type in the
3105                   function that contains all these uses. *)
3106                (* Temporarily, at least, create a new type var in this case.  If we have a polymorphic
3107                   function that is only used inside another polymorphic function but isn't declared
3108                   inside it, if we use the caller's type variable here the call won't be recognised
3109                   as polymorphic. *)
3110                (*if List.all sameTypeVar otherTypes then typ else*) mkTypeVar(generalisable, false, false, false)
3111            end
3112    
3113        |   TypeConstruction{ constr, args, name, locations, ...}  =>
3114            (
3115                (* There is a potential problem if the datatype is local including if it was
3116                   constructed in a functor.  Almost always it will have been declared after
3117                   the polymorphic function but if it happens not to have been we could set
3118                   a polymorphic function to a type that doesn't exist yet.  To avoid this
3119                   we don't allow a local datatype here and instead fall back to the
3120                   polymorphic case. *)
3121                case tcIdentifier constr of
3122                    thisConstrId as TypeId{access=Global _, ...} =>
3123                    let
3124                        val argLength = List.length args
3125                        (* This matches if it is an application of the same type constructor. *)
3126                        fun getTypeConstrs(TypeConstruction{constr, args, ...}) =
3127                                if sameTypeId(thisConstrId, tcIdentifier constr) andalso
3128                                        List.length args = argLength
3129                                then SOME args else NONE
3130                        |   getTypeConstrs _ = NONE
3131                        val allArgs = List.mapPartial (getTypeConstrs o canonical) otherTypes
3132                    in
3133                        if List.length allArgs = List.length otherTypes
3134                        then TypeConstruction{constr=constr, name=name, locations=locations,
3135                                             args = leastArgs(args :: allArgs)}
3136                        else (* At least one of these wasn't the same type constructor. *)
3137                            mkTypeVar(generalisable, false, false, false)
3138                    end
3139                |   _ => mkTypeVar(generalisable, false, false, false)
3140            )
3141
3142        |   FunctionType{ arg, result } =>
3143            let
3144                fun getFuns(FunctionType{arg, result}) = SOME(arg, result)
3145                |   getFuns _ = NONE
3146                val argResults = List.mapPartial (getFuns o canonical) otherTypes
3147            in
3148                if List.length argResults = List.length otherTypes
3149                then
3150                let
3151                    val (args, results) = ListPair.unzip argResults
3152                in
3153                    FunctionType{arg=leastGeneral(arg::args), result = leastGeneral(result::results)}
3154                end
3155                else (* At least one of these wasn't a function. *)
3156                    mkTypeVar(generalisable, false, false, false)
3157            end
3158  
3159        |   LabelledType (r as {recList=firstRec, fullList}) =>
3160            if recordIsFrozen r
3161            then
3162            let
3163                (* This matches if all the field names are the same.  Extract the types. *)
3164                fun nameMatch({name=name1: string, ...}, {name=name2, ...}) = name1 = name2
3165                fun getRecords(LabelledType{recList, ...}) =
3166                        if ListPair.allEq nameMatch (firstRec, recList) 
3167                        then SOME(List.map #typeof recList) else NONE
3168                |   getRecords _ = NONE
3169                val argResults = List.mapPartial (getRecords o canonical) otherTypes
3170            in
3171                if List.length argResults = List.length otherTypes
3172                then
3173                let
3174                    (* Use the names from the first record (they all are the same) to
3175                       build a new record. *)
3176                    val argTypes = leastArgs(List.map #typeof firstRec :: argResults)
3177                    fun recreateRecord({name, ...}, types) = {name=name, typeof=types}
3178                    val newList = ListPair.map recreateRecord(firstRec, argTypes)
3179                in
3180                    LabelledType{recList=newList, fullList=fullList }
3181                end
3182                else (* At least one of these wasn't a record. *)
3183                    mkTypeVar(generalisable, false, false, false)
3184            end
3185            else (* At this stage the record should be frozen if the program is
3186                    correct but if it isn't we could have a flexible record which
3187                    we report elsewhere. *)
3188                mkTypeVar(generalisable, false, false, false)
3189
3190        |   _ => (* May arise if there's been an error. *) mkTypeVar(generalisable, false, false, false)
3191    end
3192
3193    (* Test if this is floating point i.e. the "real" type. We could include
3194       abbreviations of real as well but it's probably not worth it. *)
3195    datatype floatKind = FloatDouble | FloatSingle
3196    
3197    local
3198        val realId = tcIdentifier realConstr and floatId = tcIdentifier floatConstr
3199
3200        fun isFloatId constr =
3201        let
3202            val id = tcIdentifier constr
3203        in
3204            if sameTypeId(id, realId) then SOME FloatDouble
3205            else if sameTypeId(id, floatId) then SOME FloatSingle
3206            else NONE
3207        end
3208    in
3209        fun isFloatingPt(TypeConstruction{args=[], constr, ...}) = isFloatId constr
3210        |   isFloatingPt(OverloadSet {typeset, ...}) =
3211            (
3212                case preferredOverload typeset of
3213                    SOME t => isFloatId t (* real only.  float is never preferred. *)
3214                |   NONE => NONE
3215            )
3216        |   isFloatingPt(TypeVar tv) = isFloatingPt (tvValue tv)
3217        |   isFloatingPt _ = NONE
3218    end
3219
3220    fun checkDiscard(t: types, lex: lexan): string option =
3221    let
3222        open DEBUG
3223        val checkLevel = getParameter reportDiscardedValuesTag (debugParams lex)
3224
3225        fun isUnit(LabelledType{recList=[], ...}) = true (* Unit is actually an empty record *)
3226        |   isUnit(TypeConstruction{
3227                    constr as TypeConstrs{identifier=TypeId{idKind=TypeFn _, ...}, ...},
3228                    args, ...}) =
3229                isUnit(makeEquivalent(constr, args))
3230        |   isUnit(TypeVar _) = true (* Allow unbound type vars *)
3231        |   isUnit _ = false
3232        
3233        fun isAFunction(FunctionType _) = true
3234        |   isAFunction(TypeConstruction{
3235                    constr as TypeConstrs{identifier=TypeId{idKind=TypeFn _, ...}, ...},
3236                    args, ...}) =
3237                isAFunction(makeEquivalent(constr, args))
3238        |   isAFunction _ = false
3239    in
3240        case checkLevel of
3241            1 => if isAFunction (eventual t) then SOME "A function value is being discarded." else NONE
3242        |   2 => if isUnit (eventual t) then NONE else SOME "A non unit value is being discarded."
3243        |   _ => NONE
3244    end
3245
3246    structure Sharing =
3247    struct
3248        type types      = types
3249        and  values     = values
3250        and  typeId     = typeId
3251        and  structVals = structVals
3252        and  typeConstrs= typeConstrs
3253        and  typeConstrSet=typeConstrSet
3254        and  typeParsetree = typeParsetree
3255        and  locationProp = locationProp
3256        and  pretty     = pretty
3257        and  lexan      = lexan
3258        and  ptProperties = ptProperties
3259        and  typeVarForm = typeVarForm
3260        and  codetree   = codetree
3261        and  matchResult = matchResult
3262        and  generalMatch = generalMatch
3263    end
3264end (* TYPETREE *);
3265