1 (* Copyright (C) 2015,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 NestedPat (S: NESTED_PAT_STRUCTS): NESTED_PAT =
15 datatype t = T of {pat: node, ty: Type.t}
17 Con of {arg: t option,
20 | Const of {const: Const.t,
23 | Layered of Var.t * t
25 | Record of t SortedRecord.t
31 fun make f (T r) = f r
38 T {pat = Record (SortedRecord.tuple ps),
39 ty = Type.tuple (Vector.map (ps, ty))}
41 fun layout (p, isDelimited) =
44 fun delimit t = if isDelimited then t else paren t
47 Con {arg, con, targs} =>
48 delimit (Pretty.conApp {arg = Option.map (arg, layoutF),
50 targs = Vector.map (targs, Type.layout)})
51 | Const {const = c, ...} => Const.layout c
52 | Layered (x, p) => delimit (seq [Var.layout x, str " as ", layoutT p])
53 | Or ps => paren (mayAlign (separateLeft (Vector.toListMap (ps, layoutT), "| ")))
58 layoutTuple = fn ps => tuple (Vector.toListMap (ps, layoutT)),
61 | Var x => Var.layout x
62 | Vector ps => vector (Vector.map (ps, layoutT))
65 and layoutF p = layout (p, false)
66 and layoutT p = layout (p, true)
76 val make = fn p => make (p, ty)
79 Con {arg, con, targs} =>
82 | SOME arg => Vector.map (flatten arg, fn arg =>
83 make (Con {arg = SOME arg, con = con, targs = targs})))
84 | Const _ => Vector.new1 p
85 | Layered (x, p) => Vector.map (flatten p, fn p => make (Layered (x, p)))
86 | Or ps => Vector.concatV (Vector.map (ps, flatten))
89 val (fs, ps) = SortedRecord.unzip rps
91 Record (SortedRecord.zip (fs, ps))
93 flattens (ps, make o record)
95 | Var _ => Vector.new1 p
96 | Vector ps => flattens (ps, make o Vector)
97 | Wild => Vector.new1 p
99 and flattens (ps, make) =
103 (Vector.map (ps, flatten), [[]], fn (fps, fpss) =>
104 List.concat (Vector.toListMap (fps, fn fp =>
105 List.map (fpss, fn fps => fp :: fps))))
107 Vector.fromListMap (fpss, fn fps => make (Vector.fromList fps))
111 Trace.trace ("NestedPat.flatten", layout, Vector.layout layout)
118 | Layered (_, p) => isRefutable p
119 | Or ps => Vector.exists (ps, isRefutable)
120 | Record rps => SortedRecord.exists (rps, isRefutable)
131 fun removeOthersReplace (p, {new, old}) =
133 fun loop (T {pat, ty}) =
137 Con {arg, con, targs} =>
138 Con {arg = Option.map (arg, loop),
146 if Var.equals (x, old)
147 then Layered (new, p)
150 | Or ps => Or (Vector.map (ps, loop))
151 | Record rps => Record (SortedRecord.map (rps, loop))
153 if Var.equals (x, old)
156 | Vector ps => Vector (Vector.map (ps, loop))
159 T {pat = pat, ty = ty}
165 val removeOthersReplace =
166 Trace.trace ("NestedPat.removeOthersReplace", fn (p, _) => layout p, layout)
170 val bogus = Var.newNoname ()
172 fun removeVars (p: t): t =
173 removeOthersReplace (p, {new = bogus, old = bogus})
176 fun replaceTypes (p: t, f: Type.t -> Type.t): t =
178 fun loop (T {pat, ty}) =
182 Con {arg, con, targs} =>
183 Con {arg = Option.map (arg, loop),
185 targs = Vector.map (targs, f)}
187 | Layered (x, p) => Layered (x, loop p)
188 | Or ps => Or (Vector.map (ps, loop))
189 | Record rps => Record (SortedRecord.map (rps, loop))
191 | Vector ps => Vector (Vector.map (ps, loop))
194 T {pat = pat, ty = f ty}
200 fun varsAndTypes (p: t): (Var.t * Type.t) list =
202 fun loop (p: t, accum: (Var.t * Type.t) list) =
204 Con {arg, ...} => (case arg of
206 | SOME p => loop (p, accum))
208 | Layered (x, p) => loop (p, (x, ty p) :: accum)
209 | Or ps => loop (Vector.first ps, accum)
210 | Record rps => SortedRecord.fold (rps, accum, loop)
211 | Var x => (x, ty p) :: accum
212 | Vector ps => Vector.fold (ps, accum, loop)