Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* Copyright (C) 1999-2006 Henry Cejtin, Matthew Fluet, Suresh |
2 | * Jagannathan, and Stephen Weeks. | |
3 | * | |
4 | * MLton is released under a BSD-style license. | |
5 | * See the file MLton-LICENSE for details. | |
6 | *) | |
7 | ||
8 | functor Env (S: ENV_STRUCTS): ENV = | |
9 | struct | |
10 | ||
11 | open S | |
12 | ||
13 | datatype 'a t = T of (Domain.t * 'a) List.t | |
14 | ||
15 | fun size (T l) = List.length l | |
16 | ||
17 | fun domain (T drs) = List.revMap (drs, #1) | |
18 | ||
19 | val fromList = T | |
20 | fun toList (T l) = l | |
21 | ||
22 | fun empty () = T [] | |
23 | ||
24 | fun single (d, r) = T [(d, r)] | |
25 | ||
26 | fun isEmpty (T l) = List.isEmpty l | |
27 | ||
28 | fun singleton dr = T [dr] | |
29 | ||
30 | fun new (ds, f) = T (List.map (ds, fn d => (d, f d))) | |
31 | ||
32 | fun map (T drs, f) = T (List.map (drs, fn (d, r) => (d, f r))) | |
33 | fun mapi (T drs, f) = T (List.map (drs, fn (d, r) => (d, f (d, r)))) | |
34 | ||
35 | fun fold (T drs, b, f) = List.fold (drs, b, fn ((_, r), b) => f (r, b)) | |
36 | fun foldi (T drs, b, f) = List.fold (drs, b, fn ((d, r), b) => f (d, r, b)) | |
37 | ||
38 | fun equal d (d', _) = Domain.equals (d, d') | |
39 | ||
40 | fun remove (T drs, d) = T (List.remove (drs, equal d)) | |
41 | ||
42 | fun extend (T drs, d, r) = | |
43 | T (List.cons ((d, r), List.remove (drs, equal d))) | |
44 | ||
45 | fun env + (T l) = List.fold (l, env, fn ((d, r), env) => extend (env, d, r)) | |
46 | ||
47 | fun plus es = List.fold (es, empty (), fn (e, accum) => accum + e) | |
48 | ||
49 | fun peek (T l, d) = | |
50 | case List.peek (l, equal d) of | |
51 | NONE => NONE | |
52 | | SOME (_, r) => SOME r | |
53 | fun lookup (env, d) = case peek (env, d) of | |
54 | SOME r => r | |
55 | | NONE => (Layout.output (Domain.layout d, Out.error) ; | |
56 | Out.newline Out.error ; | |
57 | Error.bug "Env.lookup") | |
58 | ||
59 | fun restrict (env, ds) = new (ds, fn d => lookup (env, d)) | |
60 | ||
61 | fun multiExtend (env, ds, rs) = | |
62 | case (ds, rs) of | |
63 | ([], []) => env | |
64 | | (d :: ds, r :: rs) => multiExtend (extend (env, d, r), ds, rs) | |
65 | | _ => Error.bug "Env.multiExtend" | |
66 | ||
67 | fun foreach (e, f) = List.foreach (toList e, f o #2) | |
68 | fun foreachi (e, f) = List.foreach (toList e, f) | |
69 | ||
70 | fun forall (e, f) = List.forall (toList e, f o #2) | |
71 | fun foralli (e, f) = List.forall (toList e, f) | |
72 | ||
73 | fun equals rangeEqual (e1, e2) = | |
74 | size e1 = size e2 | |
75 | andalso foralli (e1, fn (d, r) => | |
76 | case peek (e2, d) of | |
77 | NONE => false | |
78 | | SOME r' => rangeEqual (r, r')) | |
79 | ||
80 | fun layout layoutR (T ps) = | |
81 | let open Layout | |
82 | in seq [str "[", | |
83 | align (List.map (ps, fn (d, r) => | |
84 | seq [Domain.layout d, str " -> ", layoutR r])), | |
85 | str"]"] | |
86 | end | |
87 | ||
88 | fun maybeLayout (name, layoutR) env = | |
89 | if isEmpty env then Layout.empty | |
90 | else let open Layout | |
91 | in seq [str name, str " = ", layout layoutR env] | |
92 | end | |
93 | ||
94 | end | |
95 | ||
96 | functor PolyEnv (S: ENV_STRUCTS): ENV = Env (S) |