Import Upstream version 20180207
[hcoop/debian/mlton.git] / mlton / xml / xml-tree.fun
CommitLineData
7f918cf1
CE
1(* Copyright (C) 2017 Matthew Fluet.
2 * Copyright (C) 1999-2008 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 XmlTree (S: XML_TREE_STRUCTS): XML_TREE =
11struct
12
13open S
14
15structure Type =
16 struct
17 structure T = HashType (S)
18 open T
19
20 datatype dest =
21 Var of Tyvar.t
22 | Con of Tycon.t * t vector
23
24 fun dest t =
25 case Dest.dest t of
26 Dest.Var a => Var a
27 | Dest.Con x => Con x
28 end
29
30fun maybeConstrain (x, t) =
31 let
32 open Layout
33 in
34 if !Control.showTypes
35 then seq [x, str " : ", Type.layout t]
36 else x
37 end
38
39local
40 open Layout
41in
42 fun layoutTargs (ts: Type.t vector) =
43 if !Control.showTypes
44 andalso 0 < Vector.length ts
45 then list (Vector.toListMap (ts, Type.layout))
46 else empty
47end
48
49structure Pat =
50 struct
51 datatype t = T of {arg: (Var.t * Type.t) option,
52 con: Con.t,
53 targs: Type.t vector}
54
55 local
56 open Layout
57 in
58 fun layout (T {arg, con, targs}) =
59 seq [Con.layout con,
60 layoutTargs targs,
61 case arg of
62 NONE => empty
63 | SOME (x, t) =>
64 maybeConstrain (seq [str " ", Var.layout x], t)]
65 end
66
67 fun con (T {con, ...}) = con
68
69 local
70 fun make c = T {con = c, targs = Vector.new0 (), arg = NONE}
71 in
72 val falsee = make Con.falsee
73 val truee = make Con.truee
74 end
75 end
76
77structure Cases =
78 struct
79 datatype 'a t =
80 Con of (Pat.t * 'a) vector
81 | Word of WordSize.t * (WordX.t * 'a) vector
82
83 fun layout (cs, layout) =
84 let
85 open Layout
86 fun doit (v, f) =
87 align (Vector.toListMap (v, fn (x, e) =>
88 align [seq [f x, str " => "],
89 indent (layout e, 3)]))
90 in
91 case cs of
92 Con v => doit (v, Pat.layout)
93 | Word (_, v) => doit (v, WordX.layout)
94 end
95
96 fun fold (c: 'a t, b: 'b, f: 'a * 'b -> 'b): 'b =
97 let
98 fun doit l = Vector.fold (l, b, fn ((_, a), b) => f (a, b))
99 in
100 case c of
101 Con l => doit l
102 | Word (_, l) => doit l
103 end
104
105 fun map (c: 'a t, f: 'a -> 'b): 'b t =
106 let
107 fun doit l = Vector.map (l, fn (i, x) => (i, f x))
108 in
109 case c of
110 Con l => Con (doit l)
111 | Word (s, l) => Word (s, doit l)
112 end
113
114 fun foreach (c, f) = fold (c, (), fn (x, ()) => f x)
115
116 fun foreach' (c: 'a t, f: 'a -> unit, fc: Pat.t -> unit): unit =
117 let
118 fun doit l = Vector.foreach (l, fn (_, a) => f a)
119 in
120 case c of
121 Con l => Vector.foreach (l, fn (c, a) => (fc c; f a))
122 | Word (_, l) => doit l
123 end
124 end
125
126structure VarExp =
127 struct
128 datatype t = T of {targs: Type.t vector,
129 var: Var.t}
130
131 fun equals (T {targs = targs1, var = var1},
132 T {targs = targs2, var = var2}) =
133 Var.equals (var1, var2)
134 andalso Vector.equals (targs1, targs2, Type.equals)
135
136 fun mono var = T {var = var, targs = Vector.new0 ()}
137
138 local
139 fun make f (T r) = f r
140 in
141 val var = make #var
142 end
143
144 fun layout (T {var, targs, ...}) =
145 if !Control.showTypes
146 then let open Layout
147 in
148 if Vector.isEmpty targs
149 then Var.layout var
150 else seq [Var.layout var, str " ",
151 Vector.layout Type.layout targs]
152 end
153 else Var.layout var
154 end
155
156(*---------------------------------------------------*)
157(* Expressions and Declarations *)
158(*---------------------------------------------------*)
159
160datatype exp =
161 Exp of {decs: dec list,
162 result: VarExp.t}
163and primExp =
164 App of {func: VarExp.t,
165 arg: VarExp.t}
166 | Case of {test: VarExp.t,
167 cases: exp Cases.t,
168 default: (exp * Region.t) option}
169 | ConApp of {con: Con.t,
170 targs: Type.t vector,
171 arg: VarExp.t option}
172 | Const of Const.t
173 | Handle of {try: exp,
174 catch: Var.t * Type.t,
175 handler: exp}
176 | Lambda of lambda
177 | PrimApp of {args: VarExp.t vector,
178 prim: Type.t Prim.t,
179 targs: Type.t vector}
180 | Profile of ProfileExp.t
181 | Raise of {exn: VarExp.t, extend: bool}
182 | Select of {tuple: VarExp.t,
183 offset: int}
184 | Tuple of VarExp.t vector
185 | Var of VarExp.t
186and dec =
187 Exception of {arg: Type.t option,
188 con: Con.t}
189 | Fun of {decs: {lambda: lambda,
190 ty: Type.t,
191 var: Var.t} vector,
192 tyvars: Tyvar.t vector}
193 | MonoVal of {exp: primExp,
194 ty: Type.t,
195 var: Var.t}
196 | PolyVal of {exp: exp,
197 ty: Type.t,
198 tyvars: Tyvar.t vector,
199 var: Var.t}
200and lambda = Lam of {arg: Var.t,
201 argType: Type.t,
202 body: exp,
203 mayInline: bool,
204 plist: PropertyList.t}
205
206local
207 open Layout
208in
209 fun layoutConArg {arg, con} =
210 seq [Con.layout con,
211 case arg of
212 NONE => empty
213 | SOME t => seq [str " of ", Type.layout t]]
214 fun layoutTyvars ts =
215 case Vector.length ts of
216 0 => empty
217 | _ => seq [tuple (Vector.toListMap (ts, Tyvar.layout)), str " "]
218 fun layoutDec d =
219 case d of
220 Exception ca =>
221 seq [str "exception ", layoutConArg ca]
222 | Fun {decs, tyvars} =>
223 align [seq [str "val rec ", layoutTyvars tyvars],
224 indent (align (Vector.toListMap
225 (decs, fn {lambda, ty, var} =>
226 align [seq [maybeConstrain (Var.layout var, ty),
227 str " = "],
228 indent (layoutLambda lambda, 3)])),
229 3)]
230 | MonoVal {exp, ty, var} =>
231 align [seq [str "val ",
232 maybeConstrain (Var.layout var, ty), str " = "],
233 indent (layoutPrimExp exp, 3)]
234 | PolyVal {exp, ty, tyvars, var} =>
235 align [seq [str "val ",
236 if !Control.showTypes
237 then layoutTyvars tyvars
238 else empty,
239 maybeConstrain (Var.layout var, ty),
240 str " = "],
241 indent (layoutExp exp, 3)]
242 and layoutExp (Exp {decs, result}) =
243 align [str "let",
244 indent (align (List.map (decs, layoutDec)), 3),
245 str "in",
246 indent (VarExp.layout result, 3),
247 str "end"]
248 and layoutPrimExp e =
249 case e of
250 App {arg, func} => seq [VarExp.layout func, str " ", VarExp.layout arg]
251 | Case {test, cases, default} =>
252 align [seq [str "case",
253 case cases of Cases.Con _ => empty
254 | Cases.Word (size, _) => str (WordSize.toString size),
255 str " ", VarExp.layout test, str " of"],
256 Cases.layout (cases, layoutExp),
257 indent
258 (align
259 [case default of
260 NONE => empty
261 | SOME (e, _) => seq [str "_ => ", layoutExp e]],
262 2)]
263 | ConApp {arg, con, targs, ...} =>
264 seq [str "new ",
265 Con.layout con,
266 layoutTargs targs,
267 case arg of
268 NONE => empty
269 | SOME x => seq [str " ", VarExp.layout x]]
270 | Const c => Const.layout c
271 | Handle {catch, handler, try} =>
272 align [layoutExp try,
273 seq [str "handle ",
274 maybeConstrain (Var.layout (#1 catch), #2 catch),
275 str " => ", layoutExp handler]]
276 | Lambda l => layoutLambda l
277 | PrimApp {args, prim, targs} =>
278 seq [str "prim ",
279 Prim.layoutFull(prim, Type.layout),
280 layoutTargs targs,
281 str " ", tuple (Vector.toListMap (args, VarExp.layout))]
282 | Profile e => ProfileExp.layout e
283 | Raise {exn, extend} =>
284 seq [str "raise ",
285 str (if extend then "extend " else ""),
286 VarExp.layout exn]
287 | Select {offset, tuple} =>
288 seq [str "#", Int.layout offset, str " ", VarExp.layout tuple]
289 | Tuple xs => tuple (Vector.toList
290 (Vector.mapi(xs, fn (i, x) => seq
291 (* very specific case to prevent open comments *)
292 [str (if i = 0 andalso
293 (case x of (VarExp.T {var, ...}) =>
294 String.sub(Var.toString var, 0) = #"*")
295 then " "
296 else ""),
297 VarExp.layout x])))
298 | Var x => VarExp.layout x
299 and layoutLambda (Lam {arg, argType, body, mayInline, ...}) =
300 align [seq [str "fn ",
301 str (if not mayInline then "noinline " else ""),
302 maybeConstrain (Var.layout arg, argType),
303 str " => "],
304 layoutExp body]
305
306end
307
308structure Dec =
309 struct
310 type exp = exp
311 datatype t = datatype dec
312
313 val layout = layoutDec
314 end
315
316structure PrimExp =
317 struct
318 type exp = exp
319 datatype t = datatype primExp
320
321 val layout = layoutPrimExp
322 end
323
324structure Exp =
325 struct
326 datatype t = datatype exp
327
328 val layout = layoutExp
329 val make = Exp
330 fun dest (Exp r) = r
331 val decs = #decs o dest
332 val result = #result o dest
333
334 fun fromPrimExp (exp: PrimExp.t, ty: Type.t): t =
335 let val var = Var.newNoname ()
336 in Exp {decs = [Dec.MonoVal {var = var, ty = ty, exp = exp}],
337 result = VarExp.mono var}
338 end
339
340 local
341 fun make f (Exp {decs, result}, d) =
342 Exp {decs = f (d, decs),
343 result = result}
344 in val prefix = make (op ::)
345 val prefixs = make (op @)
346 end
347
348 fun enterLeave (e: t, ty: Type.t, si: SourceInfo.t): t =
349 let
350 datatype z = datatype Dec.t
351 datatype z = datatype PrimExp.t
352 fun prof f =
353 MonoVal {exp = Profile (f si),
354 ty = Type.unit,
355 var = Var.newNoname ()}
356 val exn = Var.newNoname ()
357 val res = Var.newNoname ()
358 val handler =
359 make {decs = [prof ProfileExp.Leave,
360 MonoVal {exp = Raise {exn = VarExp.mono exn,
361 extend = false},
362 ty = ty,
363 var = res}],
364 result = VarExp.mono res}
365 val touch =
366 if !Control.profile = Control.ProfileCount
367 then
368 let
369 val unit = Var.newNoname ()
370 in
371 [MonoVal {exp = Tuple (Vector.new0 ()),
372 ty = Type.unit,
373 var = unit},
374 MonoVal
375 {exp = PrimApp {args = Vector.new1 (VarExp.mono unit),
376 prim = Prim.touch,
377 targs = Vector.new1 Type.unit},
378 ty = Type.unit,
379 var = Var.newNoname ()}]
380 end
381 else []
382 val {decs, result} = dest e
383 val decs =
384 List.concat [[prof ProfileExp.Enter],
385 touch,
386 decs,
387 [prof ProfileExp.Leave]]
388 val try = make {decs = decs, result = result}
389 in
390 fromPrimExp (Handle {catch = (exn, Type.exn),
391 handler = handler,
392 try = try},
393 ty)
394 end
395
396 (*------------------------------------*)
397 (* foreach *)
398 (*------------------------------------*)
399 fun foreach {exp: t,
400 handleExp: t -> unit,
401 handlePrimExp: Var.t * Type.t * PrimExp.t -> unit,
402 handleBoundVar: Var.t * Tyvar.t vector * Type.t -> unit,
403 handleVarExp: VarExp.t -> unit}: unit =
404 let
405 fun monoVar (x, t) = handleBoundVar (x, Vector.new0 (), t)
406 fun handleVarExps xs = Vector.foreach (xs, handleVarExp)
407 fun loopExp e =
408 let val {decs, result} = dest e
409 in List.foreach (decs, loopDec)
410 ; handleVarExp result
411 ; handleExp e
412 end
413 and loopPrimExp (x: Var.t, ty: Type.t, e: PrimExp.t): unit =
414 (handlePrimExp (x, ty, e)
415 ; (case e of
416 Const _ => ()
417 | Var x => handleVarExp x
418 | Tuple xs => handleVarExps xs
419 | Select {tuple, ...} => handleVarExp tuple
420 | Lambda lambda => loopLambda lambda
421 | PrimApp {args, ...} => handleVarExps args
422 | Profile _ => ()
423 | ConApp {arg, ...} => (case arg of
424 NONE => ()
425 | SOME x => handleVarExp x)
426 | App {func, arg} => (handleVarExp func
427 ; handleVarExp arg)
428 | Raise {exn, ...} => handleVarExp exn
429 | Handle {try, catch, handler, ...} =>
430 (loopExp try
431 ; monoVar catch
432 ; loopExp handler)
433 | Case {test, cases, default} =>
434 (handleVarExp test
435 ; Cases.foreach' (cases, loopExp,
436 fn Pat.T {arg, ...} =>
437 case arg of
438 NONE => ()
439 | SOME x => monoVar x)
440 ; Option.app (default, loopExp o #1))))
441 and loopDec d =
442 case d of
443 MonoVal {var, ty, exp} =>
444 (monoVar (var, ty); loopPrimExp (var, ty, exp))
445 | PolyVal {var, tyvars, ty, exp} =>
446 (handleBoundVar (var, tyvars, ty)
447 ; loopExp exp)
448 | Exception _ => ()
449 | Fun {tyvars, decs, ...} =>
450 (Vector.foreach (decs, fn {ty, var, ...} =>
451 handleBoundVar (var, tyvars, ty))
452 ; Vector.foreach (decs, fn {lambda, ...} =>
453 loopLambda lambda))
454 and loopLambda (Lam {arg, argType, body, ...}): unit =
455 (monoVar (arg, argType); loopExp body)
456 in loopExp exp
457 end
458
459 fun ignore _ = ()
460
461 fun foreachPrimExp (e, f) =
462 foreach {exp = e,
463 handlePrimExp = f,
464 handleExp = ignore,
465 handleBoundVar = ignore,
466 handleVarExp = ignore}
467
468 fun foreachVarExp (e, f) =
469 foreach {exp = e,
470 handlePrimExp = ignore,
471 handleExp = ignore,
472 handleBoundVar = ignore,
473 handleVarExp = f}
474
475 fun foreachBoundVar (e, f) =
476 foreach {exp = e,
477 handlePrimExp = ignore,
478 handleExp = ignore,
479 handleBoundVar = f,
480 handleVarExp = ignore}
481
482 fun foreachExp (e, f) =
483 foreach {exp = e,
484 handlePrimExp = ignore,
485 handleExp = f,
486 handleBoundVar = ignore,
487 handleVarExp = ignore}
488 (* quell unused warning *)
489 val _ = foreachExp
490
491 fun hasPrim (e, f) =
492 Exn.withEscape
493 (fn escape =>
494 (foreachPrimExp (e, fn (_, _, e) =>
495 case e of
496 PrimApp {prim, ...} => if f prim then escape true
497 else ()
498 | _ => ())
499 ; false))
500
501 fun size e =
502 let val n: int ref = ref 0
503 fun inc () = n := 1 + !n
504 in foreachPrimExp (e, fn _ => inc ());
505 !n
506 end
507 val size = Trace.trace ("XmlTree.Exp.size", Layout.ignore, Int.layout) size
508 (* quell unused warning *)
509 val _ = size
510
511 fun clear (e: t): unit =
512 let open PrimExp
513 fun clearTyvars ts = Vector.foreach (ts, Tyvar.clear)
514 fun clearPat (Pat.T {arg, ...}) =
515 case arg of
516 NONE => ()
517 | SOME (x, _) => Var.clear x
518 fun clearExp e = clearDecs (decs e)
519 and clearDecs ds = List.foreach (ds, clearDec)
520 and clearDec d =
521 case d of
522 MonoVal {var, exp, ...} => (Var.clear var; clearPrimExp exp)
523 | PolyVal {var, tyvars, exp, ...} =>
524 (Var.clear var
525 ; clearTyvars tyvars
526 ; clearExp exp)
527 | Fun {tyvars, decs} =>
528 (clearTyvars tyvars
529 ; Vector.foreach (decs, fn {var, lambda, ...} =>
530 (Var.clear var
531 ; clearLambda lambda)))
532 | Exception {con, ...} => Con.clear con
533 and clearPrimExp e =
534 case e of
535 Lambda l => clearLambda l
536 | Case {cases, default, ...} =>
537 (Cases.foreach' (cases, clearExp, clearPat)
538 ; Option.app (default, clearExp o #1))
539 | Handle {try, catch, handler, ...} =>
540 (clearExp try
541 ; Var.clear (#1 catch)
542 ; clearExp handler)
543 | _ => ()
544 and clearLambda (Lam {arg, body, ...}) =
545 (Var.clear arg; clearExp body)
546 in clearExp e
547 end
548 end
549
550(*---------------------------------------------------*)
551(* Lambda *)
552(*---------------------------------------------------*)
553
554structure Lambda =
555 struct
556 type exp = exp
557 datatype t = datatype lambda
558
559 local
560 fun make f (Lam r) = f r
561 in
562 val arg = make #arg
563 val body = make #body
564 val mayInline = make #mayInline
565 end
566
567 fun make {arg, argType, body, mayInline} =
568 Lam {arg = arg,
569 argType = argType,
570 body = body,
571 mayInline = mayInline,
572 plist = PropertyList.new ()}
573
574 fun dest (Lam {arg, argType, body, mayInline, ...}) =
575 {arg = arg, argType = argType, body = body, mayInline = mayInline}
576
577 fun plist (Lam {plist, ...}) = plist
578
579 val layout = layoutLambda
580 fun equals (f:t, f':t) = PropertyList.equals (plist f, plist f')
581 end
582
583(* ------------------------------------------------- *)
584(* DirectExp *)
585(* ------------------------------------------------- *)
586structure DirectExp =
587 struct
588 open Dec PrimExp
589
590 structure Cont =
591 struct
592 type t = PrimExp.t * Type.t -> Exp.t
593
594 fun nameGen (k: VarExp.t * Type.t -> Exp.t): t =
595 fn (e, t) =>
596 case e of
597 Var x => k (x, t)
598 | _ => let val x = Var.newNoname ()
599 in Exp.prefix (k (VarExp.mono x, t),
600 MonoVal {var = x, ty = t, exp = e})
601 end
602
603 fun name (k: VarExp.t * Type.t -> Exp.t): t = nameGen k
604
605 val id: t = name (fn (x, _) => Exp {decs = [], result = x})
606
607 fun return (k: t, xt) = k xt
608 end
609
610 type t = Cont.t -> Exp.t
611
612 fun send (e: t, k: Cont.t): Exp.t = e k
613
614 fun toExp e = send (e, Cont.id)
615
616 fun fromExp (Exp {decs, result}, ty): t =
617 fn k => Exp.prefixs (k (Var result, ty), decs)
618
619 fun sendName (e, k) = send (e, Cont.name k)
620
621 fun simple (e: PrimExp.t * Type.t) k = Cont.return (k, e)
622
623 fun const c = simple (Const c, Type.ofConst c)
624
625 val string = const o Const.string
626
627 fun varExp (x, t) = simple (Var x, t)
628
629 fun var {var, targs, ty} =
630 varExp (VarExp.T {var = var, targs = targs}, ty)
631
632 fun monoVar (x, t) = var {var = x, targs = Vector.new0 (), ty = t}
633
634 fun convertsGen (es: t vector,
635 k: (VarExp.t * Type.t) vector -> Exp.t): Exp.t =
636 let
637 val n = Vector.length es
638 fun loop (i, xs) =
639 if i = n
640 then k (Vector.fromListRev xs)
641 else sendName (Vector.sub (es, i),
642 fn x => loop (i + 1, x :: xs))
643 in loop (0, [])
644 end
645
646 fun converts (es: t vector,
647 make: (VarExp.t * Type.t) vector -> PrimExp.t * Type.t): t =
648 fn k => convertsGen (es, k o make)
649
650 fun convert (e: t, make: VarExp.t * Type.t -> PrimExp.t * Type.t): t =
651 fn k => send (e, Cont.name (k o make))
652
653 fun convertOpt (e, make) =
654 case e of
655 NONE => simple (make NONE)
656 | SOME e => convert (e, make o SOME o #1)
657
658 fun tuple {exps: t vector, ty: Type.t}: t =
659 if 1 = Vector.length exps
660 then Vector.first exps
661 else converts (exps, fn xs =>
662 (PrimExp.Tuple (Vector.map (xs, #1)), ty))
663
664 fun select {tuple, offset, ty} =
665 convert (tuple, fn (tuple, _) =>
666 (Select {tuple = tuple, offset = offset}, ty))
667
668 fun conApp {con, targs, arg, ty} =
669 convertOpt (arg, fn arg =>
670 (ConApp {con = con, targs = targs, arg = arg}, ty))
671
672 local
673 fun make c () =
674 conApp {con = c,
675 targs = Vector.new0 (),
676 arg = NONE,
677 ty = Type.bool}
678 in
679 val truee = make Con.truee
680 val falsee = make Con.falsee
681 end
682
683 fun primApp {prim, targs, args, ty} =
684 converts (args, fn args =>
685 (PrimApp {prim = prim,
686 targs = targs,
687 args = Vector.map (args, #1)},
688 ty))
689
690 fun convert2 (e1, e2, make) =
691 converts (Vector.new2 (e1, e2),
692 fn xs => make (Vector.first xs, Vector.sub (xs, 1)))
693
694 fun app {func, arg, ty} =
695 convert2 (func, arg, fn ((func, _), (arg, _)) =>
696 (App {func = func, arg = arg}, ty))
697
698 fun casee {test, cases, default, ty} =
699 convert (test, fn (test, _) =>
700 (Case
701 {test = test,
702 cases = Cases.map (cases, toExp),
703 default = (Option.map
704 (default, fn (e, r) => (toExp e, r)))},
705 ty))
706
707 fun raisee {exn: t, extend: bool, ty: Type.t}: t =
708 convert (exn, fn (x, _) => (Raise {exn = x, extend = extend}, ty))
709
710 fun handlee {try, catch, handler, ty} =
711 simple (Handle {try = toExp try,
712 catch = catch,
713 handler = toExp handler},
714 ty)
715
716 fun unit () = tuple {exps = Vector.new0 (), ty = Type.unit}
717
718 fun reff (e: t): t =
719 convert (e, fn (x, t) =>
720 (PrimApp {prim = Prim.reff,
721 targs = Vector.new1 t,
722 args = Vector.new1 x},
723 Type.reff t))
724
725 fun deref (e: t): t =
726 convert (e, fn (x, t) =>
727 let
728 val t = Type.deRef t
729 in
730 (PrimApp {prim = Prim.deref,
731 targs = Vector.new1 t,
732 args = Vector.new1 x},
733 t)
734 end)
735
736 fun vectorLength (e: t): t =
737 convert (e, fn (x, t) =>
738 let
739 val t = Type.deVector t
740 in
741 (PrimApp {prim = Prim.vectorLength,
742 targs = Vector.new1 t,
743 args = Vector.new1 x},
744 Type.word (WordSize.seqIndex ()))
745 end)
746
747 fun vectorSub (e1: t, e2: t): t =
748 convert2 (e1, e2, fn ((x1, t1), (x2, _)) =>
749 let
750 val t = Type.deVector t1
751 in
752 (PrimApp {prim = Prim.vectorSub,
753 targs = Vector.new1 t,
754 args = Vector.new2 (x1, x2)},
755 t)
756 end)
757
758 fun equal (e1, e2) =
759 convert2 (e1, e2, fn ((x1, t), (x2, _)) =>
760 (PrimApp {prim = Prim.equal,
761 targs = Vector.new1 t,
762 args = Vector.new2 (x1, x2)},
763 Type.bool))
764
765 fun iff {test, thenn, elsee, ty} =
766 casee {test = test,
767 cases = Cases.Con (Vector.new2 ((Pat.truee, thenn),
768 (Pat.falsee, elsee))),
769 default = NONE,
770 ty = ty}
771
772 fun vall {var, exp}: Dec.t list =
773 let val t = ref Type.unit
774 val Exp {decs, result} =
775 sendName (exp, fn (x, t') => (t := t';
776 Exp {decs = [], result = x}))
777 in decs @ [MonoVal {var = var, ty = !t, exp = Var result}]
778 end
779
780 fun sequence es =
781 converts (es, fn xs => let val (x, t) = Vector.last xs
782 in (Var x, t)
783 end)
784
785 val bug: string -> t =
786 fn s =>
787 primApp {prim = Prim.bug,
788 targs = Vector.new0 (),
789 args = Vector.new1 (string s),
790 ty = Type.unit}
791
792 fun seq (es, make) =
793 fn k => convertsGen (es, fn xts =>
794 send (make (Vector.map (xts, varExp)), k))
795
796 fun lett {decs, body} = fn k => Exp.prefixs (send (body, k), decs)
797
798 fun let1 {var, exp, body} =
799 fn k =>
800 send (exp, fn (exp, ty) =>
801 Exp.prefix (send (body, k),
802 Dec.MonoVal {var = var, ty = ty, exp = exp}))
803
804 fun lambda {arg, argType, body, bodyType, mayInline} =
805 simple (Lambda (Lambda.make {arg = arg,
806 argType = argType,
807 body = toExp body,
808 mayInline = mayInline}),
809 Type.arrow (argType, bodyType))
810
811 fun fromLambda (l, ty) =
812 simple (Lambda l, ty)
813
814 fun detupleGen (e: PrimExp.t,
815 t: Type.t,
816 components: Var.t vector,
817 body: Exp.t): Exp.t =
818 Exp.prefixs
819 (body,
820 case Vector.length components of
821 0 => []
822 | 1 => [MonoVal {var = Vector.first components, ty = t, exp = e}]
823 | _ =>
824 let
825 val ts = Type.deTuple t
826 val tupleVar = Var.newNoname ()
827 in MonoVal {var = tupleVar, ty = t, exp = e}
828 ::
829 #2 (Vector.fold2
830 (components, ts, (0, []),
831 fn (x, t, (i, ac)) =>
832 (i + 1,
833 MonoVal {var = x, ty = t,
834 exp = Select {tuple = VarExp.mono tupleVar,
835 offset = i}}
836 :: ac)))
837 end)
838
839 fun detupleBind {tuple, components, body} =
840 fn k => send (tuple, fn (e, t) => detupleGen (e, t, components, body k))
841
842 fun detuple {tuple: t, body}: t =
843 fn k =>
844 tuple
845 (fn (e, t) =>
846 let
847 val ts = Type.deTuple t
848 in
849 case e of
850 Tuple xs => send (body (Vector.zip (xs, ts)), k)
851 | _ => let
852 val components =
853 Vector.map (ts, fn _ => Var.newNoname ())
854 in
855 detupleGen (e, t, components,
856 send (body (Vector.map2
857 (components, ts, fn (x, t) =>
858 (VarExp.mono x, t))),
859 k))
860 end
861 end)
862
863 fun devector {vector: t, length: int, body}: t =
864 fn k =>
865 let
866 val es =
867 Vector.tabulate
868 (length, fn i =>
869 vectorSub (vector, const (Const.word (WordX.fromIntInf (IntInf.fromInt i, WordSize.seqIndex ())))))
870 in
871 convertsGen (es, fn args => (body args) k)
872 end
873 end
874
875(*---------------------------------------------------*)
876(* Datatype *)
877(*---------------------------------------------------*)
878
879structure Datatype =
880 struct
881 type t = {cons: {arg: Type.t option,
882 con: Con.t} vector,
883 tycon: Tycon.t,
884 tyvars: Tyvar.t vector}
885
886 fun layout ({cons, tycon, tyvars}: t): Layout.t =
887 let
888 open Layout
889 in
890 seq [layoutTyvars tyvars,
891 Tycon.layout tycon, str " = ",
892 align
893 (separateLeft (Vector.toListMap (cons, layoutConArg),
894 "| "))]
895 end
896 end
897
898(*---------------------------------------------------*)
899(* Program *)
900(*---------------------------------------------------*)
901
902structure Program =
903 struct
904 datatype t = T of {body: Exp.t,
905 datatypes: Datatype.t vector,
906 overflow: Var.t option}
907
908 fun layout (T {body, datatypes, overflow, ...}) =
909 let
910 open Layout
911 in
912 align [str "\n\nDatatypes:",
913 align (Vector.toListMap (datatypes, Datatype.layout)),
914 seq [str "\n\nOverflow: ", Option.layout Var.layout overflow],
915 str "\n\nBody:",
916 Exp.layout body]
917 end
918
919 fun layouts (T {body, datatypes, overflow, ...}, output') =
920 let
921 open Layout
922 (* Layout includes an output function, so we need to rebind output
923 * to the one above.
924 *)
925 val output = output'
926 in
927 output (str "\n\nDatatypes:")
928 ; Vector.foreach (datatypes, output o Datatype.layout)
929 ; output (seq [str "\n\nOverflow: ", Option.layout Var.layout overflow])
930 ; output (str "\n\nBody:")
931 ; output (Exp.layout body)
932 end
933
934 fun clear (T {datatypes, body, ...}) =
935 (Vector.foreach (datatypes, fn {tycon, tyvars, cons} =>
936 (Tycon.clear tycon
937 ; Vector.foreach (tyvars, Tyvar.clear)
938 ; Vector.foreach (cons, Con.clear o #con)))
939 ; Exp.clear body)
940
941 fun layoutStats (T {datatypes, body, ...}) =
942 let
943 val numTypes = ref 0
944 fun inc _ = numTypes := 1 + !numTypes
945 val {hom, destroy} = Type.makeHom {var = inc, con = inc}
946 val numPrimExps = ref 0
947 open Layout
948 in
949 Vector.foreach (datatypes, fn {cons, ...} =>
950 Vector.foreach (cons, fn {arg, ...} =>
951 case arg of
952 NONE => ()
953 | SOME t => hom t))
954 ; (Exp.foreach
955 {exp = body,
956 handlePrimExp = fn _ => numPrimExps := 1 + !numPrimExps,
957 handleVarExp = fn _ => (),
958 handleBoundVar = hom o #3,
959 handleExp = fn _ => ()})
960 ; destroy ()
961 ; align [seq [str "num primexps in program = ", Int.layout (!numPrimExps)],
962 seq [str "num types in program = ", Int.layout (!numTypes)],
963 Type.stats ()]
964 end
965 end
966
967end