Import Debian changes 20180207-1
[hcoop/debian/mlton.git] / mlton / xml / implement-suffix.fun
CommitLineData
7f918cf1
CE
1(* Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh
2 * Jagannathan, and Stephen Weeks.
3 * Copyright (C) 1997-2000 NEC Research Institute.
4 *
5 * MLton is released under a BSD-style license.
6 * See the file MLton-LICENSE for details.
7 *)
8
9functor ImplementSuffix (S: XML_TRANSFORM_STRUCTS): XML_TRANSFORM =
10struct
11
12open S
13datatype z = datatype Dec.t
14datatype z = datatype PrimExp.t
15structure Dexp = DirectExp
16
17fun transform (Program.T {datatypes, body, overflow, ...}): Program.t =
18 let
19 (* topLevelSuffix holds the ref cell containing the function of
20 * type unit -> unit that should be called on program exit.
21 *)
22 val topLevelSuffixType = Type.arrow (Type.unit, Type.unit)
23 val topLevelSuffixVar = Var.newNoname ()
24
25 fun loop (e: Exp.t): Exp.t =
26 let
27 val {decs, result} = Exp.dest e
28 val decs = List.rev (List.fold (decs, [], fn (d, ds) =>
29 loopDec d :: ds))
30 in
31 Exp.make {decs = decs,
32 result = result}
33 end
34 and loopDec (dec: Dec.t): Dec.t =
35 case dec of
36 MonoVal b => loopMonoVal b
37 | Fun {decs, ...} =>
38 Fun {tyvars = Vector.new0 (),
39 decs = Vector.map (decs, fn {var, ty, lambda} =>
40 {var = var,
41 ty = ty,
42 lambda = loopLambda lambda})}
43 | Exception {...} => dec
44 | _ => Error.bug "ImplementSuffix: saw unexpected dec"
45 and loopMonoVal {var, ty, exp} : Dec.t =
46 let
47 fun primExp e = MonoVal {var = var, ty = ty, exp = e}
48 fun keep () = primExp exp
49 in
50 case exp of
51 Case {test, cases, default} =>
52 primExp (Case {cases = Cases.map (cases, loop),
53 default = (Option.map
54 (default, fn (e, r) =>
55 (loop e, r))),
56 test = test})
57 | ConApp {...} => keep ()
58 | Handle {try, catch = (catch, ty), handler} =>
59 primExp (Handle {try = loop try,
60 catch = (catch, ty),
61 handler = loop handler})
62 | Lambda l => primExp (Lambda (loopLambda l))
63 | PrimApp {args, prim, ...} =>
64 let
65 datatype z = datatype Prim.Name.t
66 fun deref (var, ty) =
67 primExp
68 (PrimApp {prim = Prim.deref,
69 targs = Vector.new1 ty,
70 args = Vector.new1 (VarExp.mono var)})
71 fun assign (var, ty) =
72 primExp
73 (PrimApp {prim = Prim.assign,
74 targs = Vector.new1 ty,
75 args = Vector.new2 (VarExp.mono var,
76 Vector.first args)})
77 in
78 case Prim.name prim of
79 TopLevel_getSuffix =>
80 deref (topLevelSuffixVar,
81 topLevelSuffixType)
82 | TopLevel_setSuffix =>
83 assign (topLevelSuffixVar,
84 topLevelSuffixType)
85 | _ => keep ()
86 end
87 | _ => keep ()
88 end
89 and loopLambda l =
90 let
91 val {arg, argType, body, mayInline} = Lambda.dest l
92 in
93 Lambda.make {arg = arg,
94 argType = argType,
95 body = loop body,
96 mayInline = mayInline}
97 end
98 val body = Dexp.fromExp (loop body, Type.unit)
99 val body =
100 (Dexp.sequence o Vector.new2)
101 (body,
102 Dexp.app {func = (Dexp.deref
103 (Dexp.monoVar
104 (topLevelSuffixVar,
105 Type.reff topLevelSuffixType))),
106 arg = Dexp.unit (),
107 ty = Type.unit})
108 val body =
109 Dexp.let1
110 {var = topLevelSuffixVar,
111 exp = Dexp.reff (Dexp.lambda
112 {arg = Var.newNoname (),
113 argType = Type.unit,
114 body = Dexp.bug "toplevel suffix not installed",
115 bodyType = Type.unit,
116 mayInline = true}),
117 body = body}
118 val body = Dexp.toExp body
119 in
120 Program.T {datatypes = datatypes,
121 body = body,
122 overflow = overflow}
123 end
124end