1 (* Copyright (C) 2009-2010,2012,2017 Matthew Fluet.
2 * Copyright (C) 1999-2007 Henry Cejtin, Matthew Fluet, Suresh
3 * Jagannathan, and Stephen Weeks.
4 * Copyright (C) 1997-2000 NEC Research Institute.
6 * MLton is released under a BSD-style license.
7 * See the file MLton-LICENSE for details.
10 functor TypeEnv (S: TYPE_ENV_STRUCTS): TYPE_ENV =
19 seq [str "[", l, str "]"]
32 val dontCare = dontCare
39 structure AdmitsEquality = AdmitsEquality
42 structure Field = Record.Field
43 structure Srecord = SortedRecord
44 structure Set = DisjointSet
47 * Keep a clock that the elaborator ticks for each declaration. Associate each
48 * type with a time that indicates the earliest declaration at which the type
49 * occurs. The time is used for several things.
51 * 1. When we need to generalize a type, we can tell which unknowns appear
52 * only in the declaration under consideration, and can hence be generalized.
54 * 2. Similarly, for type variables, we can tell if they appear in an earlier
55 * declaration than the one in which they are to be bound, and hence can
58 * 3. For "FlexRecord" types, we can tell when it appears only in the declaration
59 * under consideration, and can hence be converted to a "GenFlexRecord" type
60 * which allows for generalization of fields not yet known to be in the
63 * 4. For type constructors, we can tell if they are used outside of the scope
64 * of their definition. This handles the side conditions on rules 4, 17, and
72 val <= : t * t -> bool
73 val equals: t * t -> bool
74 val layout: t -> Layout.t
78 val region: t -> Region.t
79 val tick: {region: Region.t} -> unit
83 datatype t = T of {clock: int,
87 fun make f (T r) = f r
89 val clock = make #clock
90 val region = make #region
94 Layout.tuple [Int.layout (clock t),
95 Region.layout (region t)]
98 fun make f (t, t') = f (clock t, clock t')
100 val equals = make Int.equals
101 val op <= = make Int.<=
103 fun max (t, t') = if t <= t' then t' else t
104 fun min (t, t') = if t <= t' then t else t'
106 val zero = T {clock = 0, region = Region.bogus}
109 val current: t ref = ref zero
111 fun now () = !current
113 current := T {clock = 1 + clock (!current),
117 val tick = Trace.trace ("TypeEnv.Time.tick", Layout.ignore, Unit.layout) tick
125 val {get = info: Tyvar.t -> {isEquality: bool,
127 set = setInfo, ...} =
130 Property.initRaise ("TypeEnv.Tyvar.info", Tyvar.layout))
132 setInfo (a, {isEquality = ie,
136 fun make f = f o info
138 val time = make #time
139 val isEquality = make #isEquality
141 fun makeString (s, {equality}) =
144 val _ = init (a, equality)
148 fun makeNoname {equality} =
151 val _ = init (a, equality)
158 val _ = init (a', isEquality a)
165 fun makeLocalNames () =
167 val a = Char.toInt #"a"
168 val z = Char.toInt #"z"
169 val cnt = Counter.new a
170 fun reset () = Counter.reset (cnt, a)
173 val n = Counter.next cnt
176 (concat [if isEquality b then "''" else "'",
178 then concat ["a", Int.toString (n - z)]
179 else Char.toString (Char.fromInt n)])
186 fun makeLayoutPretty () =
188 val {destroy, get = layoutPretty, set = setLayoutPretty, ...} =
189 Property.destGetSet (plist, Property.initFun Tyvar.layout)
192 val {next, ...} = makeLocalNames ()
195 (bs, fn b => setLayoutPretty (b, next b))
199 layoutPretty = layoutPretty,
200 localInit = localInit}
203 fun makeLayoutPrettyLocal () =
205 val {next, reset} = makeLocalNames ()
206 val {destroy, get = layoutPretty, ...} =
207 Property.destGet (plist, Property.initFun next)
210 layoutPretty = layoutPretty,
211 reset = fn () => (reset (); destroy ())}
215 structure TyvarExt = Tyvar
222 val {get = info: t -> {admitsEquality: AdmitsEquality.t ref,
224 prettyDefault: string,
227 set = setInfo, ...} =
230 Property.initRaise ("TypeEnv.Tycon.info", Tycon.layout))
231 fun init (c, a, k, pd, r) =
232 setInfo (c, {admitsEquality = ref a,
239 (Tycon.prims, fn {tycon = c, admitsEquality = a, kind = k, name = lpd, ...} =>
240 init (c, a, k, lpd, Region.bogus))
241 val made: Tycon.t list ref = ref []
244 fun make f = f o info
246 val admitsEquality = ! o make #admitsEquality
247 val kind = make #kind
248 val prettyDefault = make #prettyDefault
249 val region = make #region
250 val time = make #time
251 fun setAdmitsEquality (t, ae) =
252 (make #admitsEquality t) := ae
254 val layoutPrettyDefault = Layout.str o prettyDefault
255 fun make {admitsEquality, kind, name,
256 prettyDefault, region} =
258 val tycon = Tycon.newString name
259 val _ = init (tycon, admitsEquality, kind,
260 prettyDefault, region)
261 val _ = List.push (made, tycon)
266 make {admitsEquality = admitsEquality c,
268 name = originalName c,
269 prettyDefault = prettyDefault c,
277 val () = made := oldMade
282 fun makeBogus {name, kind, region} =
283 make {admitsEquality = AdmitsEquality.Sometimes,
286 prettyDefault = concat ["<", name, ">"],
287 region = Option.fold (region, Region.bogus, #1)}
292 datatype t = False | True | Unknown
295 val andL: 'a list * ('a -> t) -> t
296 val andV: 'a vector * ('a -> t) -> t
297 val applyTycon: Tycon.t * t vector -> t
298 val fromBool: bool -> t
300 val layout: t -> Layout.t
304 datatype t = False | True | Unknown
308 False => Layout.str "False"
309 | True => Layout.str "True"
310 | Unknown => Layout.str "Unknown"
315 | (_, False) => False
318 | (Unknown, Unknown) => Unknown
320 fun andL (xs, f) = List.fold (xs, True, fn (x, e) => and2 (f x, e))
321 fun andV (xs, f) = Vector.fold (xs, True, fn (x, e) => and2 (f x, e))
329 | (Unknown, Unknown) => Unknown
335 | (False, False) => False
336 | (True, True) => True
337 | _ => Error.bug "TypeEnv.Equality.join"
339 fun applyTycon (c, es) =
341 datatype z = datatype AdmitsEquality.t
343 case Tycon.admitsEquality c of
345 | Sometimes => andV (es, fn e => e)
349 fun fromBool b = if b then True else False
354 datatype t = T of {canGeneralize: bool,
358 fun make f (T r) = f r
363 fun layout (T {canGeneralize, id, ...}) =
365 Layout.record [("canGeneralize", Bool.layout canGeneralize),
366 ("id", Int.layout id)]]
368 fun layoutPretty _ = str "???"
370 fun equals (u, u') = id u = id u'
373 val c = Counter.new 0
375 val newId = fn () => Counter.next c
378 fun new {canGeneralize} =
379 T {canGeneralize = canGeneralize,
382 fun join (T r, T r'): t =
383 T {canGeneralize = #canGeneralize r andalso #canGeneralize r',
387 (* Flexible record spine, i.e. a possibly extensible list of fields. *)
392 val canAddFields: t -> bool
393 val equals: t * t -> bool
394 val fields: t -> Field.t list
395 (* ensureField checks if field is there. If it is not, then ensureField
396 * will add it unless no more fields are allowed in the spine.
397 * It returns true iff it succeeds.
399 val ensureField: t * Field.t -> bool
400 val foldOverNew: t * (Field.t * 'a) list * 'b * (Field.t * 'b -> 'b) -> 'b
401 val layout: t -> Layout.t
402 val new: Field.t list -> t
403 val noMoreFields: t -> unit
404 val unify: t * t -> unit
407 datatype t = T of {id: int,
408 body: {fields: Field.t list ref,
409 more: bool ref} Set.t}
412 val c = Counter.new 0
414 val newId = fn () => Counter.next c
417 fun new fields = T {id = newId (),
418 body = Set.singleton {fields = ref fields,
421 fun equals (T {id = id1,...}, T {id = id2,...}) = id1 = id2
423 fun layout (T {body = s,...}) =
425 val {fields, more} = Set.! s
427 Layout.record [("fields", List.layout Field.layout (!fields)),
428 ("more", Bool.layout (!more))]
431 fun canAddFields (T {body = s,...}) = ! (#more (Set.! s))
432 fun fields (T {body = s,...}) = ! (#fields (Set.! s))
434 fun ensureFieldValue ({fields, more}, f) =
435 List.contains (!fields, f, Field.equals)
436 orelse (!more andalso (List.push (fields, f); true))
438 fun ensureField (T {body = s,...}, f) = ensureFieldValue (Set.! s, f)
440 fun noMoreFields (T {body = s,...}) = #more (Set.! s) := false
442 fun unify (T {body = s1,...}, T {body = s2,...}) =
444 val {fields = fs1, more = m1} = Set.! s1
445 val {fields = fs2, more = m2} = Set.! s2
446 val _ = Set.union (s1, s2)
447 val fs = List.union (!fs1, !fs2, Field.equals)
448 val m = !m1 andalso !m2
449 val _ = Set.:= (s1, {fields = ref fs, more = ref m})
454 fun foldOverNew (spine: t, fs, ac, g) =
456 (fields spine, ac, fn (f, ac) =>
457 if List.exists (fs, fn (f', _) => Field.equals (f, f'))
466 datatype t = Char | Int | Real | Word
468 val equals: t * t -> bool = op =
476 val layout = Layout.str o toString
478 val matchesTycon: t * Tycon.t -> bool =
481 Char => Tycon.isCharX c
482 | Int => Tycon.isIntX c
483 | Real => Tycon.isRealX c
484 | Word => Tycon.isWordX c
486 val defaultTycon: t -> Tycon.t =
487 fn Char => Tycon.defaultChar ()
488 | Int => Tycon.defaultInt ()
489 | Real => Tycon.defaultReal ()
490 | Word => Tycon.defaultWord ()
492 val admitsEquality: t -> Equality.t =
493 fn Char => Equality.True
494 | Int => Equality.True
495 | Real => Equality.False
496 | Word => Equality.True
499 (* Tuples of length <> 1 are always represented as records.
500 * There will never be tuples of length one.
502 datatype t = T of {equality: Equality.t ref,
503 plist: PropertyList.t,
507 Con of Tycon.t * t vector
508 | FlexRecord of {fields: fields,
510 (* GenFlexRecord only appears in type schemes.
511 * It will never be unified.
512 * The fields that are filled in after generalization are stored in
515 | GenFlexRecord of genFlexRecord
516 | Overload of Overload.t
517 | Record of t Srecord.t
518 | Unknown of Unknown.t
520 withtype fields = (Field.t * t) list
522 {extra: unit -> {field: Field.t,
523 tyvar: Tyvar.t} list,
524 fields: (Field.t * t) list,
528 fun make f (T s) = f (Set.! s)
530 val equality = make #equality
531 val plist: t -> PropertyList.t = make #plist
532 val time: t -> Time.t ref = make #time
533 val getTy: t -> ty = make #ty
539 fun layoutFields fs =
540 List.layout (Layout.tuple2 (Field.layout, layout)) fs
543 val {equality, time, ty, ...} = Set.! s
546 [("time", Time.layout (!time)),
547 ("equality", Equality.layout (!equality)),
551 paren (align [seq [str "Con ", Tycon.layout c],
552 Vector.layout layout ts])
553 | FlexRecord {fields, spine} =>
555 record [("fields", layoutFields fields),
556 ("spine", Spine.layout spine)]]
557 | GenFlexRecord {extra, fields, spine} =>
561 (fn {field, tyvar} =>
562 record [("field", Field.layout field),
563 ("tyvar", Tyvar.layout tyvar)])
565 ("fields", layoutFields fields),
566 ("spine", Spine.layout spine)]]
567 | Overload ov => Overload.layout ov
568 | Record r => Srecord.layout {record = r,
571 layoutTuple = Vector.layout layout,
573 | Unknown u => Unknown.layout u
574 | Var a => paren (seq [str "Var ", Tyvar.layout a]))]
583 val {get = opaqueExpansion: t -> (Type.t vector -> Type.t) option,
584 set = setOpaqueExpansion, ...} =
585 Property.getSet (Tycon.plist, Property.initConst NONE)
587 val opaqueExpansion =
589 ("TypeEnv.Tycon.opaqueExpansion", Tycon.layout, Layout.ignore)
592 val setOpaqueExpansion = fn (c, f) =>
593 setOpaqueExpansion (c, SOME f)
595 structure TyconExt = Tycon
597 structure LayoutPretty =
600 fun record (ds: (Field.t * bool * t) list, flexible: bool) =
602 [] => if flexible then str "{...}" else str "{}"
606 (Layout.separateRight
608 (QuickSort.sortList (ds, fn ((f, _, _), (f', _, _)) =>
612 val f = Field.layout f
613 val row = seq [f, str ": ", l]
614 val row = if b then Layout.bracket row else row
622 fun tuple (ls: t vector): t =
623 Tycon.layoutAppPretty
625 {layoutPretty = fn _ =>
626 Error.bug "TypeEnv.LayoutPretty.tuple: layoutPretty"})
633 fun makeHom {con, expandOpaque, flexRecord, genFlexRecord,
634 guard, overload, record, recursive, unknown, var} =
636 datatype status = Processing | Seen | Unseen
637 val {destroy = destroyStatus, get = status, ...} =
638 Property.destGet (plist, Property.initFun (fn _ => ref Unseen))
639 val {get, destroy = destroyProp} =
648 Seen => Error.bug "TypeEnv.Type.makeHom: impossible"
649 | Processing => recursive t
654 val _ = r := Processing
655 fun loopFields fields =
656 List.revMap (fields, fn (f, t) => (f, get t))
662 con (t, c, Vector.map (ts, get))
664 (case Tycon.opaqueExpansion c of
666 | SOME f => get (f ts))
668 if expandOpaque then yes () else no ()
670 | FlexRecord {fields, spine} =>
672 (t, {fields = loopFields fields,
674 | GenFlexRecord {extra, fields, spine} =>
677 fields = loopFields fields,
679 | Overload ov => overload (t, ov)
680 | Record r => record (t, Srecord.map (r, get))
681 | Unknown u => unknown (t, u)
682 | Var a => var (t, a)
687 | SOME res => (r := Seen; res))
693 {hom = get, destroy = destroy}
698 val {hom, destroy} = makeHom z
700 Exn.finally (fn () => hom ty, destroy)
703 fun makeLayoutPretty {expandOpaque,
706 {destroy: unit -> unit,
707 layoutPretty: t -> LayoutPretty.t} =
709 val layoutAppPretty = fn (c, ts) =>
710 Tycon.layoutAppPretty
711 (c, ts, {layoutPretty = layoutPrettyTycon})
712 fun con (_, c, ts) = layoutAppPretty (c, ts)
713 fun con0 c = layoutAppPretty (c, Vector.new0 ())
714 fun flexRecord (_, {fields, spine}) =
718 Spine.foldOverNew (spine, fields, [], fn (f, ac) =>
719 (f, false, simple (str "#???"))
721 fn ((f, t), ac) => (f, false, t) :: ac),
722 Spine.canAddFields spine)
723 fun genFlexRecord (_, {extra, fields, spine}) =
727 List.revMap (extra (), fn {field, tyvar} =>
728 (field, false, simple (layoutPrettyTyvar tyvar))),
729 fn ((f, t), ac) => (f, false, t) :: ac),
730 Spine.canAddFields spine)
731 fun overload (_, ov) = con0 (Overload.defaultTycon ov)
733 case Srecord.detupleOpt r of
738 fn (f, t) => (f, false, t)),
740 | SOME ts => LayoutPretty.tuple ts
741 fun recursive _ = simple (str "<recur>")
742 fun unknown (_, u) = simple (Unknown.layoutPretty u)
743 fun var (_, a) = simple (layoutPrettyTyvar a)
744 val {destroy, hom = layoutPretty} =
746 expandOpaque = expandOpaque,
747 flexRecord = flexRecord,
748 genFlexRecord = genFlexRecord,
749 guard = fn _ => NONE,
752 recursive = recursive,
757 layoutPretty = layoutPretty}
760 fun layoutPretty (t, {expandOpaque, layoutPrettyTycon, layoutPrettyTyvar}) =
762 val {destroy, layoutPretty} =
763 makeLayoutPretty {expandOpaque = expandOpaque,
764 layoutPrettyTycon = layoutPrettyTycon,
765 layoutPrettyTyvar = layoutPrettyTyvar}
766 val res = layoutPretty t
774 (* guarded; only invoked if '!(Tycon.admitsEquality c) = Sometimes' *)
775 fun con (_, c, es) = Equality.applyTycon (c, es)
776 fun flexRecord (_, {fields: (Field.t * Equality.t) list, spine}) =
777 if Spine.canAddFields spine
778 then Equality.Unknown
779 else Equality.andL (fields, #2)
781 fun genFlexRecord _ = Error.bug "TypeEnv.Type.getEquality.genFlexRecord"
782 (* guarded; an overload has known equality *)
783 fun overload _ = Error.bug "TypeEnv.Type.getEquality.overload"
784 fun record (_, r: Equality.t Srecord.t) =
785 Equality.andV (Srecord.toVector r, #2)
787 fun recursive _ = Error.bug "TypeEnv.Type.getEquality.recursive"
788 (* guarded; only invoked if '!(Type.equality t) = Unknown' *)
789 fun unknown (_, _) = Equality.Unknown
790 (* guarded; a tyvar has known equality *)
791 fun var _ = Error.bug "TypeEnv.Type.getEquality.var"
792 fun wrap (f, sel) arg =
795 val _ = equality (sel arg) := res
801 val e = !(equality t)
804 Equality.Unknown => NONE
808 hom (t, {con = wrap (con, #1),
809 expandOpaque = false,
810 flexRecord = wrap (flexRecord, #1),
811 genFlexRecord = genFlexRecord,
814 record = wrap (record, #1),
815 recursive = recursive,
822 ("TypeEnv.Type.getEquality", layout, Equality.layout)
831 fun deEta (t: t, tyvars: Tyvar.t vector): Tycon.t option =
834 if Vector.length ts = Vector.length tyvars
835 andalso Vector.foralli (ts, fn (i, t) =>
839 (a, Vector.sub (tyvars, i))
845 fun make {equality, time, ty}: t =
846 T (Set.singleton {equality = ref equality,
847 plist = PropertyList.new (),
851 fun newTy (ty: ty): t =
853 val (equality, time) =
857 (c, Vector.map (ts, ! o equality)),
859 (ts, Tycon.time c, fn (t, t') =>
860 Time.max (!(time t), t')))
862 Error.bug "TypeEnv.Type.newTy: GenFlexRecord"
867 (Overload.admitsEquality ov,
871 (r, Equality.True, fn (t, e') =>
872 Equality.and2 (!(equality t), e')),
874 (r, Time.zero, fn (t, t') =>
875 Time.max (!(time t), t')))
877 Error.bug "TypeEnv.Type.newTy: Unknown"
879 (Equality.fromBool (Tyvar.isEquality a),
882 make {equality = equality,
887 fun setTy (T s, ty) =
889 val {equality, plist, time, ...} = Set.! s
891 Set.:= (s, {equality = equality,
897 fun unknownAux {canGeneralize, equality, time} =
899 val u = Unknown.new {canGeneralize = canGeneralize}
900 val t = make {equality = equality,
906 val unknown = #2 o unknownAux
910 {canGeneralize = true,
911 equality = Equality.Unknown,
914 val new = Trace.trace ("TypeEnv.Type.new", Unit.layout, layout) new
916 fun newFlex {fields, spine} =
917 newTy (FlexRecord {fields = fields, spine = spine})
919 fun flexRecord record =
921 val v = Srecord.toVector record
922 val spine = Spine.new (Vector.toListMap (v, #1))
923 fun isResolved (): bool = not (Spine.canAddFields spine)
924 val t = newFlex {fields = Vector.toList v,
930 fun record r = newTy (Record r)
933 if 1 = Vector.length ts
935 else newTy (Record (Srecord.tuple ts))
937 fun con (tycon, ts) =
938 if Tycon.equals (tycon, Tycon.tuple)
940 else newTy (Con (tycon, ts))
942 fun var a = newTy (Var a)
945 structure Ops = TypeOps (structure Tycon = Tycon
948 structure UnifyResult =
950 datatype ('a, 'b) t =
955 fn NotUnifiable _ => str "NotUnifiable"
956 | Unified _ => str "Unified"
961 (* Order is important, since want specialized definitions in Type to
962 * override general definitions in Ops.
966 val unit = tuple (Vector.new0 ())
970 Con (c, _) => Tycon.equals (c, Tycon.arrow)
975 Con (c, _) => Tycon.isBool c
980 Con (c, _) => Tycon.isCharX c
981 | Overload Overload.Char => true
986 Con (c, _) => Tycon.isCPointer c
991 Con (c, _) => Tycon.isIntX c
992 | Overload Overload.Int => true
998 (case Srecord.detupleOpt r of
1000 | SOME v => Vector.isEmpty v)
1009 fun make ov () = newTy (Overload ov)
1010 datatype z = datatype Overload.t
1012 val unresolvedChar = make Char
1013 val unresolvedInt = make Int
1014 val unresolvedReal = make Real
1015 val unresolvedWord = make Word
1018 fun unresolvedString () = vector (unresolvedChar ())
1022 ("TypeEnv.Type.canUnify", layout, layout, Bool.layout)
1027 case (getTy t, getTy t') of
1028 (Unknown _, _) => true
1029 | (_, Unknown _) => true
1030 | (Con (c, ts), t') => conAnd (c, ts, t')
1031 | (t', Con (c, ts)) => conAnd (c, ts, t')
1032 | (Overload o1, Overload o2) => Overload.equals (o1, o2)
1033 | (Record r, Record r') =>
1035 val fs = Srecord.toVector r
1036 val fs' = Srecord.toVector r'
1037 in Vector.length fs = Vector.length fs'
1038 andalso Vector.forall2 (fs, fs', fn ((f, t), (f', t')) =>
1039 Field.equals (f, f')
1040 andalso canUnify (t, t'))
1042 | (Var a, Var a') => Tyvar.equals (a, a')
1044 and conAnd (c, ts, t') =
1047 Tycon.equals (c, c')
1048 andalso Vector.forall2 (ts, ts', canUnify)
1050 Vector.isEmpty ts andalso Overload.matchesTycon (ov, c)
1053 (* checkEquality t checks that t is an equality type. If t is
1054 * not an equality type, then checkEquality t returns:
1055 * - a layout object highlighting violations in t
1056 * - an alternate type, replacing violations in t with fresh
1057 * equality unification variables and a layout object
1058 * highlighting the fresh unification variables.
1060 fun checkEquality (t, {layoutPrettyTycon: Tycon.t -> Layout.t,
1061 layoutPrettyTyvar: Tyvar.t -> Layout.t}) =
1063 val layoutAppPretty = fn (c, ts) =>
1064 Tycon.layoutAppPretty
1065 (c, ts, {layoutPretty = layoutPrettyTycon})
1066 type ll = LayoutPretty.t * LayoutPretty.t
1068 fun getLay sel (llo: ll option, _) =
1069 Option.fold (llo, dontCare, sel o #1)
1071 val getLay1 = getLay #1
1072 val getLay2 = getLay #2
1074 fun getTy (_, ty) = ty
1075 (* guarded; only invoked if 'Tycon.admitsEquality c = Sometimes' *)
1076 fun con (_, c, rs) =
1077 if Vector.forall (rs, Option.isNone o #1)
1079 else SOME (layoutAppPretty
1080 (c, Vector.map (rs, getLay1)),
1082 (c, Vector.map (rs, getLay2)),
1084 (c, Vector.map (rs, getTy)))
1085 fun doRecord (fls: (Field.t * ll) list,
1086 extra: bool, mk: unit -> t) =
1093 (fls, fn (f, lll) =>
1094 (f, false, sel lll)),
1097 SOME (doit #1, doit #2, mk ())
1099 fun flexRecord (_, {fields, spine}) =
1100 doRecord (List.keepAllMap
1101 (fields, fn (f, r) =>
1102 Option.map (#1 r, fn ll => (f, ll))),
1103 Spine.canAddFields spine,
1107 List.map (fields, fn (f, r) =>
1110 Type.newFlex {fields = fields,
1114 fun genFlexRecord _ = Error.bug "TypeEnv.Type.checkEquality.genFlexRecord"
1115 (* guarded; an overload has known equality
1116 * only invoked if '!(Type.equality t) = False' *)
1117 fun overload (_, ov) =
1122 Type.unknown {canGeneralize = true,
1123 equality = Equality.True,
1126 SOME (bracket (simple (str "real")),
1127 bracket (simple (str "<equality>")),
1130 | _ => Error.bug "TypeEnv.Type.checkEquality.overload"
1132 case Srecord.detupleOpt r of
1135 val fields = Srecord.toVector r
1138 (fields, fn (f, r) =>
1139 Option.map (#1 r, fn ll => (f, ll)))
1141 doRecord (Vector.toList fields',
1142 not (Vector.length fields = Vector.length fields'),
1146 Vector.map (fields, fn (f, r) =>
1148 val fields = Srecord.fromVector fields
1154 if Vector.forall (rs, Option.isNone o #1)
1156 else SOME (LayoutPretty.tuple (Vector.map (rs, getLay1)),
1157 LayoutPretty.tuple (Vector.map (rs, getLay2)),
1158 Type.tuple (Vector.map (rs, getTy)))
1160 fun recursive _ = Error.bug "TypeEnv.Type.checkEquality.recursive"
1161 fun unknown (t, _) =
1162 case !(equality t) of
1166 Type.unknown {canGeneralize = true,
1167 equality = Equality.True,
1170 SOME (bracket (simple (str "<non-equality>")),
1171 bracket (simple (str "<equality>")),
1174 | Equality.True => NONE
1175 | Equality.Unknown => NONE
1176 (* guarded; a tyvar has known equality
1177 * only invoked if '!(Type.equality t) = False' *)
1179 if Tyvar.isEquality a
1180 then Error.bug "TypeEnv.Type.checkEquality.var"
1183 Type.unknown {canGeneralize = true,
1184 equality = Equality.True,
1187 SOME (bracket (simple (layoutPrettyTyvar a)),
1188 bracket (simple (str "<equality>")),
1191 fun wrap (f, sel) arg =
1197 equality t := Equality.True
1200 | SOME (l1, l2, t) =>
1202 (* Need extra guarding of Con, because proceeding with
1203 * hom/con would recursively force all Unknowns in type
1204 * args to Equality.True, even if tycon is
1205 * AdmitsEquality.Never. *)
1207 case !(equality t) of
1208 Equality.True => SOME (NONE, t)
1209 | _ => (case Type.getTy t of
1211 (case Tycon.admitsEquality c of
1212 AdmitsEquality.Always => SOME (NONE, t)
1213 | AdmitsEquality.Sometimes => NONE
1214 | AdmitsEquality.Never =>
1217 Type.unknown {canGeneralize = true,
1218 equality = Equality.True,
1221 SOME (SOME ((bracket o layoutAppPretty)
1222 (c, Vector.map (ts, fn _ => dontCare)),
1223 bracket (simple (str "<equality>"))),
1227 val res : ll option * t =
1228 hom (t, {con = wrap (con, #1),
1229 expandOpaque = false,
1230 flexRecord = wrap (flexRecord, #1),
1231 genFlexRecord = genFlexRecord,
1233 overload = wrap (overload, #1),
1234 record = wrap (record, #1),
1235 recursive = recursive,
1236 unknown = wrap (unknown, #1),
1237 var = wrap (var, #1)})
1241 | (SOME (l1, l2), t) =>
1245 (* checkTime (t, bound) checks that all components of t have
1246 * times no larger than bound. If t has components with time
1247 * larger than bound, then checkTime (t, bound) returns:
1248 * - a layout object highlighting violations in t
1249 * - an alternate type, replacing violations in t with fresh
1250 * unification variables at time bound and a layout object
1251 * highlighting the fresh unification variables.
1252 * - a list of violating tycons
1253 * - a list of violating tyvars
1255 fun makeCheckTime {layoutPrettyTycon: Tycon.t -> Layout.t,
1256 layoutPrettyTyvar: Tyvar.t -> Layout.t} =
1258 val layoutAppPretty = fn (c, ts) =>
1259 Tycon.layoutAppPretty
1260 (c, ts, {layoutPretty = layoutPrettyTycon})
1261 val times: Time.t list ref = ref []
1262 val tycons: Tycon.t list ref = ref []
1263 val tyvars: Tyvar.t list ref = ref []
1264 type lll = LayoutPretty.t * LayoutPretty.t * LayoutPretty.t
1266 fun getLay sel (lllo: lll option, _) =
1267 Option.fold (lllo, dontCare, sel o #1)
1269 val getLay1 = getLay #1
1270 val getLay2 = getLay #2
1271 val getLay3 = getLay #3
1273 fun getTy (_, ty) = ty
1274 fun con bound (_, c, rs) =
1275 if Time.<= (Tycon.time c, bound)
1276 then if Vector.forall (rs, Option.isNone o #1)
1278 else SOME (layoutAppPretty
1279 (c, Vector.map (rs, getLay1)),
1281 (c, Vector.map (rs, getLay2)),
1283 (c, Vector.map (rs, getLay3)),
1285 (c, Vector.map (rs, getTy)))
1288 Type.unknownAux {canGeneralize = true,
1289 equality = Equality.Unknown,
1292 List.push (times, bound)
1293 ; List.push (tycons, c)
1294 ; SOME ((bracket o layoutAppPretty)
1295 (c, Vector.map (rs, getLay2)),
1297 (c, Vector.map (rs, getLay2)),
1298 bracket (simple (Unknown.layoutPretty u)),
1301 fun doRecord (fls: (Field.t * lll) list,
1302 extra: bool, mk: unit -> t) =
1309 (fls, fn (f, lll) =>
1310 (f, false, sel lll)),
1313 SOME (doit #1, doit #2, doit #3, mk ())
1315 fun flexRecord (_, {fields, spine}) =
1316 doRecord (List.keepAllMap
1317 (fields, fn (f, r) =>
1318 Option.map (#1 r, fn lll => (f, lll))),
1319 Spine.canAddFields spine,
1323 List.map (fields, fn (f, r) =>
1326 Type.newFlex {fields = fields,
1330 case Srecord.detupleOpt r of
1333 val fields = Srecord.toVector r
1336 (fields, fn (f, r) =>
1337 Option.map (#1 r, fn lll => (f, lll)))
1339 doRecord (Vector.toList fields',
1340 not (Vector.length fields = Vector.length fields'),
1344 Vector.map (fields, fn (f, r) =>
1346 val fields = Srecord.fromVector fields
1352 if Vector.forall (rs, Option.isNone o #1)
1354 else SOME (LayoutPretty.tuple (Vector.map (rs, getLay1)),
1355 LayoutPretty.tuple (Vector.map (rs, getLay2)),
1356 LayoutPretty.tuple (Vector.map (rs, getLay3)),
1357 Type.tuple (Vector.map (rs, getTy)))
1358 fun var bound (_, a) =
1359 if Time.<= (Tyvar.time a, bound)
1363 Type.unknownAux {canGeneralize = true,
1364 equality = Equality.Unknown,
1367 List.push (times, bound)
1368 ; List.push (tyvars, a)
1369 ; SOME (bracket (simple (layoutPrettyTyvar a)),
1370 simple (layoutPrettyTyvar a),
1371 bracket (simple (Unknown.layoutPretty u)),
1374 fun genFlexRecord _ = Error.bug "TypeEnv.Type.checkTime.genFlexRecord"
1375 fun recursive _ = Error.bug "TypeEnv.Type.checkTime.recursive"
1376 fun checkTime (t, bound) =
1377 if Time.<= (!(time t), bound)
1380 fun wrap (f, sel) arg =
1389 | SOME (l1, l2, l3, t) =>
1391 ; (SOME (l1, l2, l3), t))
1393 if Time.<= (!(time t), bound)
1396 val res : lll option * t =
1397 hom (t, {con = wrap (con bound, #1),
1398 expandOpaque = false,
1399 flexRecord = wrap (flexRecord, #1),
1400 genFlexRecord = genFlexRecord,
1402 overload = wrap (fn _ => NONE, #1),
1403 record = wrap (record, #1),
1404 recursive = recursive,
1405 unknown = wrap (fn _ => NONE, #1),
1406 var = wrap (var bound, #1)})
1410 | (SOME (l1, _, l3), t) =>
1413 fun finishCheckTime () =
1414 {times = List.removeDuplicates (!times, Time.equals),
1415 tycons = List.removeDuplicates (!tycons, Tycon.equals),
1416 tyvars = List.removeDuplicates (!tyvars, Tyvar.equals)}
1418 {checkTime = checkTime,
1419 finishCheckTime = finishCheckTime}
1422 datatype z = datatype UnifyResult.t
1426 ("TypeEnv.Type.unify", layout, layout,
1428 (LayoutPretty.t * LayoutPretty.t, unit) UnifyResult.t -> Layout.t)
1431 {layoutPretty: t -> LayoutPretty.t,
1432 layoutPrettyTycon: Tycon.t -> Layout.t,
1433 layoutPrettyTyvar: Tyvar.t -> Layout.t}) =
1435 val layoutAppPretty = fn (c, ts) =>
1436 Tycon.layoutAppPretty
1437 (c, ts, {layoutPretty = layoutPrettyTycon})
1438 val checkEquality = fn t =>
1439 checkEquality (t, {layoutPrettyTycon = layoutPrettyTycon,
1440 layoutPrettyTyvar = layoutPrettyTyvar})
1441 val {checkTime, finishCheckTime} =
1442 makeCheckTime {layoutPrettyTycon = layoutPrettyTycon,
1443 layoutPrettyTyvar = layoutPrettyTyvar}
1446 (fn (outer as T s, outer' as T s') =>
1447 if Set.equals (s, s')
1451 fun notUnifiable (l: LayoutPretty.t, l': LayoutPretty.t) =
1452 NotUnifiable (l, l')
1453 fun notUnifiableBracket (l, l') =
1454 notUnifiable (bracket l, bracket l')
1455 fun flexToRecord (fields, spine) =
1456 (Vector.fromList fields,
1457 Spine.canAddFields spine)
1458 fun rigidToRecord r =
1459 (Srecord.toVector r,
1461 fun flexToFlexToRecord (fields, spine, equality, time, outer, spine') =
1465 (Spine.fields spine', fn f' =>
1466 ignore (Spine.ensureField (spine, f')))
1469 (spine, fields, fields, fn (f, fields) =>
1473 {canGeneralize = true,
1474 equality = Equality.or2 (equality, Equality.Unknown),
1479 val _ = setTy (outer, FlexRecord {fields = fields, spine = spine})
1481 flexToRecord (fields, spine)
1483 fun flexToRigidToRecord (fields, spine, equality, time, outer, r') =
1487 (Srecord.toVector r', fn (f', _) =>
1488 ignore (Spine.ensureField (spine, f')))
1489 val () = Spine.noMoreFields spine
1492 (spine, fields, fields, fn (f, fields) =>
1496 {canGeneralize = true,
1497 equality = Equality.or2 (equality, Equality.Unknown),
1502 val r = Srecord.fromVector (Vector.fromList fields)
1503 val _ = setTy (outer, Record r)
1507 fun oneFlex ({fields, spine}, equality, time, outer, r', swap) =
1509 (flexToRigidToRecord (fields, spine, equality, time, outer, r'),
1511 fn () => Unified (Record r'),
1512 notUnifiable o (fn (l, l') =>
1516 fun genFlexError () =
1517 Error.bug "TypeEnv.Type.unify: GenFlexRecord"
1518 val {equality, time, ty = t, plist} = Set.! s
1519 val {equality = equality', time = time', ty = t', ...} = Set.! s'
1521 notUnifiableBracket (layoutPretty outer,
1522 layoutPretty outer')
1523 fun unifys (ts, ts', yes, no) =
1525 val us = Vector.map2 (ts, ts', unify)
1528 (us, fn Unified _ => true | _ => false)
1537 Unified _ => (dontCare, dontCare)
1538 | NotUnifiable (l, l') => (l, l')))
1543 fun conAnd (c, ts, t, t', swap) =
1546 if swap then (z', z) else (z, z')
1550 if Tycon.equals (c, c')
1552 if Vector.length ts <> Vector.length ts'
1566 (maybe (lay ts, lay ts'))
1574 fun lay ls = layoutAppPretty (c, ls)
1577 (maybe (lay ls, lay ls'))
1581 if Vector.isEmpty ts
1582 andalso Overload.matchesTycon (ov, c)
1587 fun oneUnknown (u: Unknown.t,
1588 equality: Equality.t,
1595 (* This should fail if the unknown occurs in t. *)
1596 fun con (_, _, ts) =
1597 Vector.exists (ts, fn b => b)
1598 fun doFields fields =
1599 List.exists (fields, fn (_, b) => b)
1600 fun flexRecord (_, {fields, spine = _}) =
1602 fun record (_, r) = Srecord.exists (r, fn b => b)
1603 fun unknown (_, u') = Unknown.equals (u, u')
1608 expandOpaque = false,
1609 flexRecord = flexRecord,
1610 genFlexRecord = fn _ =>
1611 Error.bug "TypeEnv.Type.unify.oneUnknown: genFlexRecord",
1612 guard = fn _ => NONE,
1616 Error.bug "TypeEnv.Type.unify.oneUnknown: recursive",
1623 fun err (l, (t'', l'')) =
1624 (setTy (outer, getTy t'')
1632 (case checkEquality outer' of
1634 | SOME (l, (t'', l'')) =>
1635 err (l, (t'', l'')))
1637 (case checkTime (outer', time) of
1639 | SOME (l, (t'', l'')) =>
1640 err (l, (t'', l'')))
1645 (Unknown r, Unknown r') =>
1646 (case (!equality, !equality') of
1647 (Equality.True, Equality.False) =>
1649 (simple (str "<equality>"),
1650 simple (str "<non-equality>"))
1651 | (Equality.False, Equality.True) =>
1653 (simple (str "<non-equality>"),
1654 simple (str "<equality>"))
1655 | _ => Unified (Unknown (Unknown.join (r, r'))))
1657 oneUnknown (u, !equality, !time, outer, t', outer', false)
1658 | (_, Unknown u') =>
1659 oneUnknown (u', !equality', !time', outer', t, outer, true)
1660 | (Con (c, ts), _) => conAnd (c, ts, t', t, false)
1661 | (_, Con (c, ts)) => conAnd (c, ts, t, t', true)
1662 | (FlexRecord f, Record r') =>
1663 oneFlex (f, !equality, !time, outer, r', false)
1664 | (Record r, FlexRecord f') =>
1665 oneFlex (f', !equality', !time', outer', r, true)
1666 | (FlexRecord {fields = fields, spine = spine},
1667 FlexRecord {fields = fields', spine = spine'}) =>
1671 val () = Spine.unify (spine, spine')
1674 (fields, fields', fn ((f, t), ac) =>
1675 if List.exists (fields', fn (f', _) =>
1676 Field.equals (f, f'))
1680 Unified (FlexRecord {fields = fields,
1685 (flexToFlexToRecord (fields, spine, !equality, !time, outer, spine'),
1686 flexToFlexToRecord (fields', spine', !equality', !time', outer', spine),
1689 | (GenFlexRecord _, _) => genFlexError ()
1690 | (_, GenFlexRecord _) => genFlexError ()
1691 | (Overload ov1, Overload ov2) =>
1692 if Overload.equals (ov1, ov2)
1695 | (Record r, Record r') =>
1696 (case (Srecord.detupleOpt r,
1697 Srecord.detupleOpt r') of
1700 (rigidToRecord r, rigidToRecord r',
1701 fn () => Unified (Record r),
1703 | (SOME ts, SOME ts') =>
1704 if Vector.length ts = Vector.length ts'
1707 fn () => Unified (Record r),
1710 (LayoutPretty.tuple ls,
1711 LayoutPretty.tuple ls'))
1714 | (Var a, Var a') =>
1715 if Tyvar.equals (a, a')
1721 NotUnifiable (l, l') =>
1722 NotUnifiable (l, l')
1725 val () = Set.union (s, s')
1726 val () = time := Time.min (!time, !time')
1727 val () = equality := Equality.join (!equality, !equality')
1729 Set.:= (s, {equality = equality,
1739 and unifyRecords ((fields: (Field.t * t) vector,
1741 (fields': (Field.t * t) vector,
1745 fun subset (fields, fields',
1746 ac, dots, ac', dots',
1749 (fields, (ac, dots, ac', dots'),
1750 fn ((f, t), (ac, dots, ac', dots')) =>
1751 case Vector.peek (fields', fn (f', _) =>
1752 Field.equals (f, f')) of
1754 ((f, true, dontCare) :: ac, dots, ac', dots')
1757 then (ac, dots, ac', dots')
1759 case unify (t, t') of
1760 NotUnifiable (l, l') =>
1761 ((f, false, l) :: ac, dots,
1762 (f, false, l') :: ac', dots')
1763 | Unified _ => (ac, true, ac', true))
1764 val (ac, dots, ac', dots') =
1765 subset (fields, fields', [], dots, [], dots', false)
1766 val (ac', dots', ac, dots) =
1767 subset (fields', fields, ac', dots', ac, dots, true)
1771 | _ => no (LayoutPretty.record (ac, dots),
1772 LayoutPretty.record (ac', dots'))
1774 val res = unify (t, t')
1777 NotUnifiable ((l, _), (l', _)) =>
1779 val {times, tycons, tyvars} =
1782 if List.isEmpty tycons andalso List.isEmpty tyvars
1785 fun doit (xs, lay) =
1787 (List.map (xs, fn x => (x, lay x)),
1788 fn ((_, l1), (_, l2)) =>
1789 String.<= (Layout.toString l1,
1790 Layout.toString l2))
1791 val tycons = doit (tycons, layoutPrettyTycon)
1792 val tyvars = doit (tyvars, layoutPrettyTyvar)
1794 List.map (tycons, #2)
1795 @ List.map (tyvars, #2)
1799 if List.length tys > 1
1800 then str "types would escape their scope: "
1801 else str "type would escape its scope: ",
1802 seq (Layout.separate (tys, ", "))],
1803 (Layout.align o List.map)
1804 (tycons, fn (c, _) =>
1805 seq [str "escape from: ",
1806 Region.layout (Tycon.region c)]),
1807 (Layout.align o List.map)
1809 seq [str "escape to: ",
1810 Region.layout (Time.region t)])]
1813 NotUnifiable (l, l',
1816 | Unified () => Unified ()
1820 val {get: Tycon.t -> (t * Tycon.t) option, set, ...} =
1821 Property.getSetOnce (Tycon.plist, Property.initConst NONE)
1823 fun setSynonym (c, c') = set (c, SOME (con (c, Vector.new0 ()), c'))
1829 (CharSize.all, fn s =>
1830 setSynonym (Tycon.char s,
1831 Tycon.word (WordSize.fromBits (CharSize.bits s))))
1835 (IntSize.all, fn s =>
1836 setSynonym (Tycon.int s,
1837 Tycon.word (WordSize.fromBits (IntSize.bits s))))
1839 structure Overload =
1844 fn Char => con (Tycon.defaultChar (), Vector.new0 ())
1845 | Int => con (Tycon.defaultInt (), Vector.new0 ())
1846 | Real => con (Tycon.defaultReal (), Vector.new0 ())
1847 | Word => con (Tycon.defaultWord (), Vector.new0 ())
1850 fun 'a simpleHom {con: t * Tycon.t * 'a vector -> 'a,
1852 record: t * (Field.t * 'a) vector -> 'a,
1853 replaceSynonyms: bool,
1854 var: t * Tyvar.t -> 'a} =
1856 val unit = con (unit, Tycon.tuple, Vector.new0 ())
1858 fun sortFields (fields: (Field.t * 'a) list) =
1860 val a = Array.fromList fields
1862 QuickSort.sortArray (a, fn ((f, _), (f', _)) =>
1867 fun unsorted (t, fields: (Field.t * 'a) list) =
1869 val v = sortFields fields
1873 fun genFlexRecord (t, {extra, fields, spine = _}) =
1876 (extra (), fields, fn ({field, tyvar}, ac) =>
1877 (field, var (Type.var tyvar, tyvar)) :: ac))
1878 fun flexRecord (t, {fields, spine}) =
1879 if Spine.canAddFields spine
1880 then Error.bug "TypeEnv.Type.simpleHom: flexRecord"
1883 (spine, fields, fields, fn (f, ac) =>
1885 fun recursive _ = Error.bug "TypeEnv.Type.simpleHom.recursive"
1887 if not replaceSynonyms
1895 | SOME (t, c) => (t, c)
1899 fun overload (t', ov) =
1901 val t = Overload.defaultType ov
1902 val _ = unify (t, t',
1903 {layoutPretty = fn _ =>
1904 Error.bug "TypeEnv.Type.simpleHom.overload: layoutPretty",
1905 layoutPrettyTycon = fn _ =>
1906 Error.bug "TypeEnv.Type.simpleHom.overload: layoutPrettyTycon",
1907 layoutPrettyTyvar = fn _ =>
1908 Error.bug "TypeEnv.Type.simpleHom.overload: layoutPrettyTyvar"})
1910 con (t, Overload.defaultTycon ov, Vector.new0 ())
1914 expandOpaque = expandOpaque,
1915 flexRecord = flexRecord,
1916 genFlexRecord = genFlexRecord,
1917 guard = fn _ => NONE,
1918 overload = overload,
1919 record = fn (t, r) => record (t, Srecord.toVector r),
1920 recursive = recursive,
1921 unknown = fn _ => unknown,
1929 General of {bound: unit -> Tyvar.t vector,
1930 canGeneralize: bool,
1931 flexes: Type.genFlexRecord list,
1932 tyvars: Tyvar.t vector,
1937 fn General {ty, ...} => ty
1941 fn General {bound, ty, ...} => (bound (), ty)
1942 | Mono ty => (Vector.new0 (), ty)
1945 fn General {bound, ...} => Kind.Arity (Vector.length (bound ()))
1946 | Mono _ => Kind.Arity 0
1950 Mono t => Type.layout t
1951 | General {canGeneralize, tyvars, ty, ...} =>
1952 Layout.record [("canGeneralize", Bool.layout canGeneralize),
1953 ("tyvars", Vector.layout Tyvar.layout tyvars),
1954 ("ty", Type.layout ty)]
1956 fun make {canGeneralize, tyvars, ty} =
1957 if Vector.isEmpty tyvars
1959 else General {bound = fn () => tyvars,
1960 canGeneralize = canGeneralize,
1967 fun fromTycon (tycon: Tycon.t): t =
1969 val kind = Tycon.kind tycon
1972 Kind.Arity arity => arity
1973 | Kind.Nary => Error.bug "TypeEnv.Scheme.fromTycon: Kind.Nary"
1977 Tyvar.makeNoname {equality = false})
1980 {canGeneralize = true,
1981 ty = Type.con (tycon, Vector.map (tyvars, Type.var)),
1985 fun instantiateAux (t: t, subst) =
1987 Mono ty => {args = fn () => Vector.new0 (),
1989 | General {canGeneralize, flexes, tyvars, ty, ...} =>
1990 (case Type.deEta (ty, tyvars) of
1995 (tyvars, fn (i, a) =>
1996 subst {canGeneralize = canGeneralize,
1997 equality = Tyvar.isEquality a,
2000 {args = fn () => types,
2001 instance = Type.con (tycon, types)}
2006 val {destroy = destroyTyvarInst,
2007 get = tyvarInst: Tyvar.t -> Type.t option,
2008 set = setTyvarInst} =
2009 Property.destGetSetOnce (Tyvar.plist,
2010 Property.initConst NONE)
2013 (tyvars, fn (i, a) =>
2015 val t = subst {canGeneralize = canGeneralize,
2016 equality = Tyvar.isEquality a,
2018 val _ = setTyvarInst (a, SOME t)
2022 type z = {isNew: bool, ty: Type.t}
2023 fun isNew {isNew = b, ty = _} = b
2024 fun keep ty = {isNew = false, ty = ty}
2025 fun con (ty, c, zs) =
2026 if Vector.exists (zs, isNew)
2028 ty = Type.con (c, Vector.map (zs, #ty))}
2030 val flexInsts = ref []
2031 fun genFlexRecord (_, {extra = _, fields, spine}) =
2033 val fields = List.revMap (fields, fn (f, t: z) =>
2035 val flex = newFlex {fields = fields,
2037 val _ = List.push (flexInsts, {flex = flex,
2044 if Srecord.exists (r, isNew)
2046 ty = Type.record (Srecord.map (r, #ty))}
2049 (* If we get here, there has already been a type error
2050 * in the user's program, so we return a new type to avoid
2051 * compounding the error.
2057 NONE => {isNew = false, ty = ty}
2058 | SOME ty => {isNew = true, ty = ty}
2059 val {ty: Type.t, ...} =
2060 Type.hom (ty, {con = con,
2061 expandOpaque = false,
2062 flexRecord = keep o #1,
2063 genFlexRecord = genFlexRecord,
2064 guard = fn _ => NONE,
2065 overload = keep o #1,
2067 recursive = recursive,
2068 unknown = keep o #1,
2070 val _ = destroyTyvarInst ()
2071 val flexInsts = !flexInsts
2072 fun args (): Type.t vector =
2075 (flexes, Vector.toList types,
2076 fn ({fields, spine, ...}, ac) =>
2080 (spine, fields, ac, fn (f, ac) =>
2083 | SOME t => t) :: ac)
2085 case List.peek (flexInsts,
2086 fn {spine = spine', ...} =>
2087 Spine.equals (spine, spine')) of
2088 NONE => done (fn _ => NONE)
2089 | SOME {flex, ...} =>
2091 fun peekFields (fields, f) =
2093 (List.peek (fields, fn (f', _) =>
2094 Field.equals (f, f')),
2098 (case Type.getTy flex of
2099 FlexRecord {fields, ...} =>
2100 (fn f => peekFields (fields, f))
2101 | GenFlexRecord {extra, fields, ...} =>
2103 case peekFields (fields, f) of
2109 Field.equals (f, field)),
2113 (fn f => Srecord.peek (r, f))
2114 | _ => Error.bug "TypeEnv.instantiate': General:strange flexInst")
2123 #instance (instantiateAux (s, fn {index, ...} => Vector.sub (ts, index)))
2127 (s, fn {canGeneralize, equality, ...} =>
2128 Type.unknown {canGeneralize = canGeneralize,
2129 equality = if equality
2131 else Equality.Unknown,
2132 time = Time.now ()})
2135 Trace.trace ("TypeEnv.Scheme.instantiate", layout, Type.layout o #instance)
2140 val (tyvars, _) = dest s
2141 val tyvars = Vector.map (tyvars, Tyvar.makeLike)
2143 (tyvars, apply (s, (Vector.map (tyvars, Type.var))))
2148 val (tyvars, _) = dest s
2149 val tyvars = Vector.map (tyvars, fn _ => Tyvar.makeNoname {equality = true})
2151 (tyvars, apply (s, (Vector.map (tyvars, Type.var))))
2154 fun admitsEquality s =
2156 val (_, ty) = freshEq s
2158 case !(Type.equality ty) of
2159 Equality.False => false
2160 | Equality.True => true
2161 | Equality.Unknown => Error.bug "TypeEnv.Scheme.admitsEquality: Unknown"
2164 val admitsEquality =
2165 Trace.trace ("TypeEnv.Scheme.admitsEquality", layout, Bool.layout)
2168 fun checkEquality (s, {layoutPrettyTycon}) =
2170 fun layoutPrettyTyvar _ =
2171 Error.bug "TypeEnv.Scheme.checkEquality.layoutPrettyTyvar"
2172 val (_, ty) = freshEq s
2176 (ty, {layoutPrettyTycon = layoutPrettyTycon,
2177 layoutPrettyTyvar = layoutPrettyTyvar}),
2178 fn ((l, _), _) => l)
2181 fun haveUnknowns s: bool =
2183 fun con (_, _, bs) = Vector.exists (bs, fn b => b)
2185 val {destroy, hom} =
2188 expandOpaque = false,
2189 flexRecord = fn (_, {fields, ...}) => List.exists (fields, #2),
2190 genFlexRecord = (fn (_, {fields, ...}) =>
2191 List.exists (fields, #2)),
2192 guard = fn _ => NONE,
2194 record = fn (_, r) => Srecord.exists (r, fn b => b),
2196 unknown = fn _ => true,
2198 val res = hom (ty s)
2205 fun 'a close region =
2207 val beforeGen = Time.now ()
2208 val () = Time.tick region
2212 {error: 'a * Layout.t * Tyvar.t list -> unit,
2214 layoutPrettyTyvar}) =>
2217 fun checkTime (t, bound) =
2219 val {checkTime, finishCheckTime} =
2220 Type.makeCheckTime {layoutPrettyTycon = layoutPrettyTycon,
2221 layoutPrettyTyvar = layoutPrettyTyvar}
2223 Option.map (checkTime (t, bound), fn z =>
2224 (z, finishCheckTime ()))
2229 (varTypes, fn ({isExpansive, ty, var}) =>
2231 then {isExpansive = false,
2233 else (case checkTime (ty, beforeGen) of
2234 NONE => {isExpansive = true,
2236 | SOME (((l, _), _), {tyvars, ...}) =>
2237 (error (var, l, tyvars)
2238 ; {isExpansive = false,
2241 val tyvars = Vector.toList ensure
2242 (* Convert all the unknown types bound at this level into tyvars.
2243 * Convert all the FlexRecords bound at this level into
2246 val (flexes, tyvars) =
2248 (varTypes, fn {ty, ...} =>
2249 Time.<= (!(Type.time ty), beforeGen))
2253 val tyvars = ref tyvars
2254 fun flexRecord (t, _) =
2256 val (fields, spine) =
2257 case Type.getTy t of
2258 Type.FlexRecord {fields, spine} =>
2260 | _ => Error.bug "TypeEnv.close.flexRecord: not FlexRecord"
2263 tyvar = Tyvar.makeNoname {equality = false}}
2268 List.map (fields, fn (f, _) => (f, ()))
2275 (old, fields, fn ({field, ...}, ac) =>
2279 (spine, fields, old, fn (f, ac) =>
2286 val gfr = {extra = extra,
2289 val _ = List.push (flexes, gfr)
2292 (t, Type.GenFlexRecord gfr)
2294 fun unknown (t, Unknown.T {canGeneralize, ...}) =
2295 if not canGeneralize
2298 val equality = Type.equality t
2303 Equality.False => false
2304 | Equality.True => true
2305 | Equality.Unknown =>
2306 (equality := Equality.False
2308 val _ = List.push (tyvars, a)
2314 if Time.<= (!(Type.time t), beforeGen)
2317 val {destroy, hom} =
2320 expandOpaque = false,
2321 flexRecord = flexRecord,
2322 genFlexRecord = fn _ => (),
2324 overload = fn _ => (),
2325 record = fn _ => (),
2326 recursive = fn _ => (),
2329 val _ = Vector.foreach (varTypes, hom o #ty)
2334 (* For all fields that were added to the generalized flex records,
2335 * add a type variable.
2340 (flexes, tyvars, fn ({extra, fields, spine}, ac) =>
2342 val extra = extra ()
2345 (spine, fields, ac, fn (f, ac) =>
2346 case List.peek (extra, fn {field, ...} =>
2347 Field.equals (f, field)) of
2348 NONE => Error.bug "TypeEnv.close.bound: GenFlex missing field"
2349 | SOME {tyvar, ...} => tyvar :: ac)
2353 (varTypes, fn {isExpansive, ty} =>
2356 else Scheme.General {bound = bound,
2357 canGeneralize = true,
2359 tyvars = Vector.fromList tyvars,
2371 fun homConVar {con, expandOpaque, var} =
2374 if 1 = Vector.length ts
2375 then Vector.first ts
2376 else con (t, Tycon.tuple, ts)
2378 simpleHom {con = con,
2379 expandOpaque = expandOpaque,
2380 record = fn (t, fs) => tuple (t, Vector.map (fs, #2)),
2381 replaceSynonyms = true,
2385 fun makeHom {con, expandOpaque, var} =
2386 homConVar {con = fn (_, c, ts) => con (c, ts),
2387 expandOpaque = expandOpaque,
2388 var = fn (_, a) => var a}
2392 val {hom, destroy} =
2394 {con = fn (t, _, _) => (t, NONE),
2395 expandOpaque = false,
2396 record = fn (t, fs) => (t,
2397 SOME (Vector.map (fs, fn (f, (t, _)) =>
2399 replaceSynonyms = true,
2400 var = fn (t, _) => (t, NONE)}
2403 NONE => Error.bug "TypeEnv.Type.deRecord"
2412 val {destroy, hom} =
2414 {con = fn (t, c, ts) => (t,
2415 if Tycon.equals (c, Tycon.tuple)
2416 then SOME (Vector.map (ts, #1))
2418 expandOpaque = false,
2419 var = fn (t, _) => (t, NONE)}
2420 val res = #2 (hom t)
2427 Trace.trace ("TypeEnv.Type.deTupleOpt", layout,
2428 Option.layout (Vector.layout layout))
2431 fun hom (t, {con, expandOpaque = e, record, replaceSynonyms = r,
2434 val {hom, destroy} =
2435 simpleHom {con = fn (_, c, v) => con (c, v),
2437 record = fn (_, fs) => record (Srecord.fromVector fs),
2438 replaceSynonyms = r,
2439 var = fn (_, a) => var a}
2447 hom (t, {con = Type.con,
2448 expandOpaque = false,
2449 record = Type.record,
2450 replaceSynonyms = false,
2454 fn (t1, t2, {error, layoutPretty, layoutPrettyTycon, layoutPrettyTyvar}) =>
2455 case unify (t1, t2, {layoutPretty = layoutPretty,
2456 layoutPrettyTycon = layoutPrettyTycon,
2457 layoutPrettyTyvar = layoutPrettyTyvar}) of
2458 NotUnifiable (l1, l2, extra) => error (l1, l2, extra)
2462 fn (t, bound, {layoutPrettyTycon, layoutPrettyTyvar}) =>
2464 val {checkTime, finishCheckTime} =
2465 makeCheckTime {layoutPrettyTycon = layoutPrettyTycon,
2466 layoutPrettyTyvar = layoutPrettyTyvar}
2469 (checkTime (t, bound), fn ((l, _), (ty, _)) =>
2470 (l, ty, let val {tycons, tyvars, ...} = finishCheckTime ()
2471 in {tycons = tycons, tyvars = tyvars}