Import Upstream version 20180207
[hcoop/debian/mlton.git] / mlton / elaborate / elaborate-sigexp.fun
CommitLineData
7f918cf1
CE
1(* Copyright (C) 2010,2012,2015,2017 Matthew Fluet.
2 * Copyright (C) 1999-2006 Henry Cejtin, Matthew Fluet, Suresh
3 * Jagannathan, and Stephen Weeks.
4 * Copyright (C) 1997-2000 NEC Research Institute.
5 *
6 * MLton is released under a BSD-style license.
7 * See the file MLton-LICENSE for details.
8 *)
9
10functor ElaborateSigexp (S: ELABORATE_SIGEXP_STRUCTS): ELABORATE_SIGEXP =
11struct
12
13open S
14
15local
16 open Ast
17in
18 structure Atype = Type
19 structure DatBind = DatBind
20 structure DatatypeRhs = DatatypeRhs
21 structure SharingEquation = SharingEquation
22 structure Longstrid = Longstrid
23 structure Longtycon = Longtycon
24 structure Record = Record
25 structure Sigexp = Sigexp
26 structure Sigid = Sigid
27 structure SortedRecord = SortedRecord
28 structure Spec = Spec
29 structure TypBind = TypBind
30 structure Atyvar = Tyvar
31 structure WhereEquation = WhereEquation
32end
33
34local
35 open Env
36in
37 structure Interface = Interface
38 structure StructureTycon =
39 struct
40 open Tycon
41 open TypeEnv.TyconExt
42 end
43 structure TyvarEnv = TyvarEnv
44end
45structure StructureEnv = Env
46structure Env = StructureEnv.InterfaceEnv
47
48local
49 open Interface
50in
51 structure AdmitsEquality = AdmitsEquality
52 structure Cons = Cons
53 structure Kind = Kind
54 structure FlexibleTycon = FlexibleTycon
55 structure Scheme = Scheme
56 structure Status = Status
57 structure Tycon = Tycon
58 structure Type = Type
59 structure TypeStr = TypeStr
60 structure Tyvar = Tyvar
61end
62
63local
64 open Control.Elaborate
65in
66 fun check (c: (bool,bool) t, keyword: string, region) =
67 if current c
68 then ()
69 else
70 let
71 open Layout
72 in
73 Control.error
74 (region,
75 str (concat (if expert c
76 then [keyword, " disallowed"]
77 else [keyword, " disallowed, compile with -default-ann '",
78 name c, " true'"])),
79 empty)
80 end
81end
82
83fun elaborateType (ty: Atype.t, E: Env.t): Type.t =
84 let
85 fun makeBogus (mc, ts) =
86 let
87 val arity = Vector.length ts
88 val (name, region) =
89 Option.fold
90 (mc, ("t", NONE), fn (c, _) =>
91 (Longtycon.toString c,
92 SOME (Longtycon.region c)))
93 val c =
94 StructureTycon.makeBogus
95 {name = name,
96 kind = Kind.Arity arity,
97 region = region}
98 in
99 Type.con (Tycon.Rigid c, ts)
100 end
101 fun loop (ty: Atype.t): Type.t =
102 case Atype.node ty of
103 Atype.Var a => (* rule 44 *)
104 (case TyvarEnv.lookupTyvar a of
105 NONE => makeBogus (NONE, Vector.new0 ())
106 | SOME a => Type.var a)
107 | Atype.Con (c, ts) => (* rules 46, 47 *)
108 let
109 val ts = Vector.map (ts, loop)
110 fun normal () =
111 case Env.lookupLongtycon (E, c) of
112 NONE => makeBogus (SOME c, ts)
113 | SOME s =>
114 let
115 val kind = TypeStr.kind s
116 val numArgs = Vector.length ts
117 val ts =
118 case kind of
119 Kind.Arity n =>
120 let
121 fun error () =
122 let
123 open Layout
124 fun doit n =
125 seq [str "[",
126 case n of
127 0 => empty
128 | 1 => str "_"
129 | _ => seq [str "(",
130 (seq o separate)
131 (List.tabulate (n, fn _ => str "_"),
132 ", "),
133 str ")"],
134 str "] ",
135 Ast.Longtycon.layout c]
136 in
137 Control.error
138 (Atype.region ty,
139 seq [str "type constructor applied to incorrect number of type arguments: ",
140 Ast.Longtycon.layout c],
141 align [seq [str "expects: ", doit n],
142 seq [str "but got: ", doit numArgs],
143 seq [str "in: ", Atype.layout ty]])
144 end
145 in
146 case Int.compare (n, numArgs) of
147 LESS =>
148 (error (); Vector.prefix (ts, n))
149 | EQUAL => ts
150 | GREATER =>
151 (error ()
152 ; Vector.concat
153 [ts,
154 Vector.tabulate
155 (n - numArgs, fn _ =>
156 makeBogus
157 (NONE,
158 Vector.new0 ()))])
159 end
160 | Kind.Nary => ts
161 in
162 TypeStr.apply (s, ts)
163 end
164 in
165 case (Ast.Longtycon.split c, Vector.length ts) of
166 (([], c), 2) =>
167 if Ast.Tycon.equals (c, Ast.Tycon.arrow)
168 then Type.arrow (Vector.sub (ts, 0),
169 Vector.sub (ts, 1))
170 else normal ()
171 | _ => normal ()
172 end
173 | Atype.Paren t => loop t
174 | Atype.Record r => (* rules 45, 49 *)
175 Type.record
176 (SortedRecord.fromVector
177 (Vector.map
178 (Record.toVector r,
179 fn (f, (_, t)) => (f, loop t))))
180 val ty = loop ty
181 in
182 ty
183 end
184
185val elaborateType =
186 Trace.trace ("ElaborateSigexp.elaborateType", Atype.layout o #1, Type.layout)
187 elaborateType
188
189fun elaborateScheme (tyvars: Tyvar.t vector, ty: Atype.t, E): Scheme.t =
190 let
191 val ty = elaborateType (ty, E)
192 in
193 Scheme.make (tyvars, ty)
194 end
195
196fun elaborateTypedescs (typedescs: {tycon: Ast.Tycon.t,
197 tyvars: Ast.Tyvar.t vector} vector,
198 {equality: bool},
199 E,
200 nest): unit =
201 Vector.foreach
202 (typedescs, fn {tycon = name, tyvars} =>
203 let
204 val admitsEquality =
205 if equality
206 then AdmitsEquality.Sometimes
207 else AdmitsEquality.Never
208 val kind = Kind.Arity (Vector.length tyvars)
209 val prettyDefault =
210 concat (List.separate (rev (Ast.Tycon.toString name :: nest), "."))
211 val flex = FlexibleTycon.new {admitsEquality = admitsEquality,
212 hasCons = false,
213 kind = kind,
214 prettyDefault = prettyDefault,
215 region = Ast.Tycon.region name}
216 val tycon = Tycon.Flexible flex
217 in
218 Env.extendTycon (E, name, TypeStr.tycon (tycon, equality))
219 end)
220
221fun elabTypBind (typBind: TypBind.t, E, {sequential}) =
222 let
223 fun mkDef {def, tycon = _, tyvars} =
224 TyvarEnv.scope
225 (tyvars, fn tyvars =>
226 let
227 val realization =
228 TypeStr.def (elaborateScheme (tyvars, def, E))
229 val _ =
230 TypeStr.pushSpec (realization, Ast.Type.region def)
231 in
232 realization
233 end)
234 val TypBind.T bs = TypBind.node typBind
235 in
236 if sequential
237 then Vector.foreach
238 (bs, fn b as {tycon, ...} =>
239 Env.extendTycon (E, tycon, mkDef b))
240 else Vector.foreach2
241 (bs, Vector.map (bs, mkDef), fn ({tycon, ...}, str) =>
242 Env.extendTycon (E, tycon, str))
243 end
244
245fun elaborateDatBind (datBind: DatBind.t, E, nest): unit =
246 let
247 val DatBind.T {datatypes, withtypes} = DatBind.node datBind
248 (* Build enough of an interface so that that the constructor argument
249 * types can be elaborated.
250 *)
251 val datatypes =
252 Vector.map
253 (datatypes, fn {cons, tycon = name, tyvars} =>
254 let
255 val arity = Vector.length tyvars
256 val kind = Kind.Arity arity
257 val prettyDefault =
258 concat (List.separate (rev (Ast.Tycon.toString name :: nest), "."))
259 val flex = FlexibleTycon.new {admitsEquality = AdmitsEquality.Sometimes,
260 hasCons = true,
261 kind = kind,
262 prettyDefault = prettyDefault,
263 region = Ast.Tycon.region name}
264 val tycon = Tycon.Flexible flex
265 val _ = Env.extendTycon (E, name, TypeStr.tycon (tycon, false))
266 in
267 {cons = cons,
268 flex = flex,
269 name = name,
270 tycon = tycon,
271 tyvars = tyvars}
272 end)
273 val _ = if TypBind.isEmpty withtypes
274 then ()
275 else check (Control.Elaborate.allowSigWithtype,
276 "withtype in signatures",
277 TypBind.region withtypes)
278 (* To match semantics of withtype in Core,
279 * type binds are elaborated simultaneously.
280 *)
281 val _ = elabTypBind (withtypes, E, {sequential = false})
282 val datatypes =
283 Vector.map
284 (datatypes, fn {cons, flex, name, tycon, tyvars} =>
285 let
286 val cons =
287 Vector.map
288 (cons, fn (name, arg) =>
289 TyvarEnv.scope
290 (tyvars, fn tyvars =>
291 {arg = Option.map (arg, fn t => elaborateType (t, E)),
292 name = name,
293 tyvars = tyvars}))
294 in
295 {cons = cons,
296 flex = flex,
297 name = name,
298 tycon = tycon}
299 end)
300 (* Maximize equality *)
301 val change = ref false
302 fun loop () =
303 let
304 val _ =
305 Vector.foreach
306 (datatypes, fn {cons, flex, ...} =>
307 let
308 val isEquality = ref true
309 val () =
310 Vector.foreach
311 (cons, fn {arg, tyvars, ...} =>
312 Option.foreach
313 (arg, fn arg =>
314 let
315 val argScheme =
316 Scheme.make (tyvars, arg)
317 in
318 if Scheme.admitsEquality argScheme
319 then ()
320 else isEquality := false
321 end))
322 datatype z = datatype AdmitsEquality.t
323 in
324 case FlexibleTycon.admitsEquality flex of
325 Always => Error.bug "ElaborateSigexp.elaborateDatBind: Always"
326 | Never => ()
327 | Sometimes =>
328 if !isEquality
329 then ()
330 else (FlexibleTycon.setAdmitsEquality (flex, Never)
331 ; change := true)
332 end)
333 in
334 if !change
335 then (change := false; loop ())
336 else ()
337 end
338 val () = loop ()
339 val () =
340 Vector.foreach
341 (datatypes, fn {cons, name, tycon, ...} =>
342 let
343 val cons =
344 Vector.map
345 (cons, fn {arg, name, tyvars} =>
346 let
347 val res =
348 Type.con (tycon, Vector.map (tyvars, Type.var))
349 val ty =
350 case arg of
351 NONE => res
352 | SOME arg => Type.arrow (arg, res)
353 val scheme =
354 Scheme.make (tyvars, ty)
355 val () =
356 Env.extendCon (E, name, scheme)
357 in
358 {name = name,
359 scheme = scheme}
360 end)
361 val () =
362 Env.rebindTycon
363 (E, name, TypeStr.data (tycon, Cons.fromVector cons, false))
364 in
365 ()
366 end)
367 in
368 ()
369 end
370
371val traceElaborateSigexp =
372 Trace.trace2 ("ElaborateSigexp.elaborateSigexp",
373 Sigexp.layout,
374 fn {isTop, nest} => Layout.record [("isTop", Bool.layout isTop),
375 ("nest", List.layout Layout.str nest)],
376 Option.layout Interface.layout)
377val traceElaborateSpec =
378 Trace.trace2 ("ElaborateSigexp.elaborateSpec",
379 Spec.layout,
380 fn {nest} => Layout.record [("nest", List.layout Layout.str nest)],
381 Unit.layout)
382
383(* rule 65 *)
384fun elaborateSigexp (sigexp: Sigexp.t, {env = E: StructureEnv.t, nest: string list}): Interface.t option =
385 let
386 val strE = E
387 val E = StructureEnv.makeInterfaceEnv E
388 fun elaborateSigexp arg : Interface.t option =
389 traceElaborateSigexp
390 (fn (sigexp: Sigexp.t, {isTop, nest}) =>
391 case Sigexp.node sigexp of
392 Sigexp.Spec spec =>
393 (* rule 62 *)
394 SOME (#1 (Env.makeInterface (E, {isTop = isTop},
395 fn () => elaborateSpec (spec, {nest = nest}))))
396 | Sigexp.Var x =>
397 (* rule 63 *)
398 Option.map (Env.lookupSigid (E, x), Interface.copy)
399 | Sigexp.Where {sigexp, equations} =>
400 (* rule 64 *)
401 let
402 val time = Interface.Time.tick ()
403 in
404 Option.map
405 (elaborateSigexp (sigexp, {isTop = false, nest = nest}), fn I =>
406 let
407 val {layoutPrettyTycon = layoutPrettyEnvTycon,
408 layoutPrettyFlexTycon, ...} =
409 StructureEnv.makeLayoutPrettyTyconAndFlexTycon
410 (strE, E, SOME I, {prefixUnset = true})
411 val _ =
412 Vector.foreach
413 (equations, fn eqn =>
414 case WhereEquation.node eqn of
415 WhereEquation.Type {longtycon, ty, tyvars} =>
416 Option.app
417 (Interface.lookupLongtycon
418 (I, longtycon, Longtycon.region longtycon,
419 {prefix = []}),
420 fn (name, s) =>
421 let
422 val realization =
423 TyvarEnv.scope
424 (tyvars, fn tyvars =>
425 TypeStr.def (elaborateScheme (tyvars, ty, E)))
426 in
427 TypeStr.wheree
428 {layoutPrettyEnvTycon = layoutPrettyEnvTycon,
429 layoutPrettyFlexTycon = layoutPrettyFlexTycon,
430 realization = realization,
431 region = WhereEquation.region eqn,
432 time = time,
433 ty = {name = fn () => Longtycon.layout longtycon,
434 region = Longtycon.region longtycon,
435 spec = Ast.Tycon.region name,
436 tyStr = s}}
437 end))
438 in
439 I
440 end)
441 end) arg
442 and elaborateSpec arg : unit =
443 traceElaborateSpec
444 (fn (spec: Spec.t, {nest}) =>
445 case Spec.node spec of
446 Spec.Datatype rhs =>
447 (* rules 71, 72 *)
448 (case DatatypeRhs.node rhs of
449 DatatypeRhs.DatBind b => elaborateDatBind (b, E, nest)
450 | DatatypeRhs.Repl {lhs, rhs} =>
451 Option.app
452 (Env.lookupLongtycon (E, rhs), fn s =>
453 let
454 val _ = TypeStr.pushSpec (s, Longtycon.region rhs)
455 val _ = Env.extendTycon (E, lhs, TypeStr.repl s)
456 val _ =
457 Vector.foreach
458 (Cons.dest (TypeStr.cons s), fn {name, scheme} =>
459 Env.extendCon (E, name, scheme))
460 in
461 ()
462 end))
463 | Spec.Empty =>
464 (* rule 76 *)
465 ()
466 | Spec.Eqtype typedescs =>
467 (* rule 70 *)
468 elaborateTypedescs (typedescs, {equality = true}, E, nest)
469 | Spec.Exception cons =>
470 (* rule 73 *)
471 Vector.foreach
472 (cons, fn (name: Ast.Con.t, arg: Ast.Type.t option) =>
473 let
474 val ty =
475 case arg of
476 NONE => Type.exn
477 | SOME t =>
478 let
479 val t = elaborateType (t, E)
480 in
481 Type.arrow (t, Type.exn)
482 end
483 val scheme = Scheme.make (Vector.new0 (), ty)
484 val _ = Env.extendExn (E, name, scheme)
485 in
486 ()
487 end)
488 | Spec.IncludeSigexp sigexp =>
489 (* rule 75 *)
490 Option.app (elaborateSigexp (sigexp, {isTop = false, nest = nest}), fn I =>
491 Env.openInterface (E, I, Sigexp.region sigexp))
492 | Spec.IncludeSigids sigids =>
493 (* Appendix A, p.59 *)
494 Vector.foreach (sigids, fn x =>
495 Option.app
496 (Env.lookupSigid (E, x), fn I =>
497 Env.openInterface
498 (E, Interface.copy I, Sigid.region x)))
499 | Spec.Seq (s, s') =>
500 (* rule 77 *)
501 (elaborateSpec (s, {nest = nest})
502 ; elaborateSpec (s', {nest = nest}))
503 | Spec.Sharing {equation, spec} =>
504 (* rule 78 and section G.3.3 *)
505 let
506 val time = Interface.Time.tick ()
507 (* Reifying the interface of spec is expensive,
508 * so collect all `sharing` equations that
509 * constrain the same spec.
510 *)
511 val (spec, equations) =
512 let
513 fun loop (spec, equations) =
514 case Spec.node spec of
515 Spec.Sharing {equation, spec} =>
516 loop (spec, equation::equations)
517 | _ => (spec, equations)
518 in
519 loop (spec, [equation])
520 end
521 val (I, _) =
522 Env.makeInterface
523 (E, {isTop = false},
524 fn () => elaborateSpec (spec, {nest = nest}))
525 val () = Env.openInterface (E, I, Spec.region spec)
526 val {layoutPrettyTycon = layoutPrettyEnvTycon,
527 layoutPrettyFlexTycon, ...} =
528 StructureEnv.makeLayoutPrettyTyconAndFlexTycon
529 (strE, E, NONE, {prefixUnset = true})
530 val () =
531 List.foreach
532 (equations, fn eqn =>
533 case SharingEquation.node eqn of
534 SharingEquation.Structure ss =>
535 let
536 (* The following implements the "all
537 * pairs" sharing as specified in
538 * Appendix A (and described in
539 * Appendix G.3.3).
540 *)
541 fun loop Is =
542 case Is of
543 [] => ()
544 | (long1, I1) :: Is =>
545 (List.foreach
546 (Is, fn (long2, I2) =>
547 Interface.share
548 {layoutPrettyEnvTycon = layoutPrettyEnvTycon,
549 layoutPrettyFlexTycon = layoutPrettyFlexTycon,
550 I1 = I1, long1 = long1,
551 I2 = I2, long2 = long2,
552 region = SharingEquation.region eqn,
553 time = time})
554 ; loop Is)
555 val Is =
556 List.keepAllMap
557 (ss, fn s =>
558 Option.map
559 (Interface.lookupLongstrid
560 (I, s, Longstrid.region s, {prefix = []}),
561 fn I => (s, I)))
562 in
563 loop Is
564 end
565 | SharingEquation.Type cs =>
566 ignore
567 (List.fold
568 (cs, NONE, fn (c', so) =>
569 case (so, Interface.lookupLongtycon (I, c', Longtycon.region c', {prefix = []})) of
570 (NONE, NONE) => NONE
571 | (SOME _, NONE) => so
572 | (NONE, SOME (n', s')) => SOME (c', n', s')
573 | (SOME (c, n, s), SOME (n', s')) =>
574 let
575 fun mkTy (c, n, s) =
576 {name = fn () => Longtycon.layout c,
577 region = Longtycon.region c,
578 spec = Ast.Tycon.region n,
579 tyStr = s}
580 val _ =
581 TypeStr.share
582 {layoutPrettyEnvTycon = layoutPrettyEnvTycon,
583 layoutPrettyFlexTycon = layoutPrettyFlexTycon,
584 region = SharingEquation.region eqn,
585 time = time,
586 ty1 = mkTy (c, n, s),
587 ty2 = mkTy (c', n', s')}
588 in
589 SOME (c', n', s')
590 end)))
591 in
592 ()
593 end
594 | Spec.Structure ss =>
595 (* rules 74, 84 *)
596 let
597 val ss =
598 Vector.map
599 (ss, fn (strid, sigexp) =>
600 (strid,
601 case elaborateSigexp
602 (sigexp,
603 {isTop = false,
604 nest = (Ast.Strid.toString strid)::nest}) of
605 NONE => Interface.empty
606 | SOME I => I))
607 in
608 Vector.foreach
609 (ss, fn (strid, I) =>
610 Env.extendStrid
611 (E, strid, I))
612 end
613 | Spec.Type typedescs =>
614 (* rule 69 *)
615 elaborateTypedescs (typedescs, {equality = false}, E, nest)
616 | Spec.TypeDefs typBind =>
617 (* Abbreviation on page 59 combined with rules 77 and 80. *)
618 elabTypBind (typBind, E, {sequential = true})
619 | Spec.Val xts =>
620 (* rules 68, 79 *)
621 Vector.foreach
622 (xts, fn (x, t) =>
623 Env.extendVid
624 (E, Ast.Vid.fromVar x, Status.Var,
625 let
626 val tyvars =
627 let
628 val tyvars = ref []
629 fun loop t =
630 case Ast.Type.node t of
631 Atype.Var a =>
632 if List.contains (!tyvars, a, Atyvar.equals)
633 then ()
634 else List.push (tyvars, a)
635 | Atype.Con (_, ts) =>
636 Vector.foreach (ts, loop)
637 | Atype.Paren t => loop t
638 | Atype.Record r => Record.foreach (r, loop o #2)
639 val () = loop t
640 in
641 Vector.fromListRev (!tyvars)
642 end
643 in
644 TyvarEnv.scope
645 (tyvars, fn tyvars =>
646 elaborateScheme (tyvars, t, E))
647 end))) arg
648 in
649 elaborateSigexp (sigexp, {isTop = true, nest = nest})
650 end
651
652val elaborateSigexp =
653 fn (sigexp, {env = E, nest}) =>
654 case Sigexp.node sigexp of
655 Sigexp.Var x => StructureEnv.lookupSigid (E, x)
656 | _ => elaborateSigexp (sigexp, {env = E, nest = nest})
657
658val elaborateSigexp =
659 Trace.trace2 ("ElaborateSigexp.elaborateSigexp",
660 Sigexp.layout,
661 Layout.ignore,
662 Layout.ignore)
663 elaborateSigexp
664
665structure Env = StructureEnv
666
667end