Mercurial > urweb
comparison src/sqlcache.sml @ 2286:0bdfec16a01d
Fix issue with one-element caches. Locking still WIP.
author | Ziv Scully <ziv@mit.edu> |
---|---|
date | Fri, 13 Nov 2015 01:04:32 -0500 |
parents | b7615e0ac4b0 |
children | 98f96a976ede |
comparison
equal
deleted
inserted
replaced
2285:ad3ce1528f71 | 2286:0bdfec16a01d |
---|---|
1 structure Sqlcache :> SQLCACHE = struct | 1 structure Sqlcache :> SQLCACHE = struct |
2 | 2 |
3 open Mono | 3 |
4 (*********************) | |
5 (* General Utilities *) | |
6 (*********************) | |
4 | 7 |
5 structure IK = struct type ord_key = int val compare = Int.compare end | 8 structure IK = struct type ord_key = int val compare = Int.compare end |
6 structure IS = IntBinarySet | 9 structure IS = IntBinarySet |
7 structure IM = IntBinaryMap | 10 structure IM = IntBinaryMap |
8 structure SK = struct type ord_key = string val compare = String.compare end | 11 structure SK = struct type ord_key = string val compare = String.compare end |
9 structure SS = BinarySetFn(SK) | 12 structure SS = BinarySetFn(SK) |
10 structure SM = BinaryMapFn(SK) | 13 structure SM = BinaryMapFn(SK) |
14 structure IIMM = MultimapFn(structure KeyMap = IM structure ValSet = IS) | |
11 structure SIMM = MultimapFn(structure KeyMap = SM structure ValSet = IS) | 15 structure SIMM = MultimapFn(structure KeyMap = SM structure ValSet = IS) |
12 | |
13 (* ASK: how do we deal with heap reallocation? *) | |
14 | 16 |
15 fun id x = x | 17 fun id x = x |
16 | 18 |
17 fun iterate f n x = if n < 0 | 19 fun iterate f n x = if n < 0 |
18 then raise Fail "Can't iterate function negative number of times." | 20 then raise Fail "Can't iterate function negative number of times." |
19 else if n = 0 | 21 else if n = 0 |
20 then x | 22 then x |
21 else iterate f (n-1) (f x) | 23 else iterate f (n-1) (f x) |
24 | |
25 (* From the MLton wiki. *) | |
26 infix 3 <\ fun x <\ f = fn y => f (x, y) (* Left section *) | |
27 infix 3 \> fun f \> y = f y (* Left application *) | |
28 | |
29 fun mapFst f (x, y) = (f x, y) | |
30 | |
31 (* Option monad. *) | |
32 fun obind (x, f) = Option.mapPartial f x | |
33 fun oguard (b, x) = if b then x else NONE | |
34 fun omap f = fn SOME x => SOME (f x) | _ => NONE | |
35 fun omap2 f = fn (SOME x, SOME y) => SOME (f (x,y)) | _ => NONE | |
36 fun osequence ys = List.foldr (omap2 op::) (SOME []) ys | |
37 | |
38 fun indexOf test = | |
39 let | |
40 fun f n = | |
41 fn [] => NONE | |
42 | (x::xs) => if test x then SOME n else f (n+1) xs | |
43 in | |
44 f 0 | |
45 end | |
46 | |
47 | |
48 (************) | |
49 (* Settings *) | |
50 (************) | |
51 | |
52 open Mono | |
22 | 53 |
23 (* Filled in by [addFlushing]. *) | 54 (* Filled in by [addFlushing]. *) |
24 val ffiInfoRef : {index : int, params : int} list ref = ref [] | 55 val ffiInfoRef : {index : int, params : int} list ref = ref [] |
25 | 56 |
26 fun resetFfiInfo () = ffiInfoRef := [] | 57 fun resetFfiInfo () = ffiInfoRef := [] |
57 | 88 |
58 val alwaysConsolidateRef = ref true | 89 val alwaysConsolidateRef = ref true |
59 fun setAlwaysConsolidate b = alwaysConsolidateRef := b | 90 fun setAlwaysConsolidate b = alwaysConsolidateRef := b |
60 fun getAlwaysConsolidate () = !alwaysConsolidateRef | 91 fun getAlwaysConsolidate () = !alwaysConsolidateRef |
61 | 92 |
93 | |
94 (************************) | |
95 (* Really Useful Things *) | |
96 (************************) | |
97 | |
62 (* Used to have type context for local variables in MonoUtil functions. *) | 98 (* Used to have type context for local variables in MonoUtil functions. *) |
63 val doBind = | 99 val doBind = |
64 fn (env, MonoUtil.Exp.RelE (x, t)) => MonoEnv.pushERel env x t NONE | 100 fn (env, MonoUtil.Exp.RelE (x, t)) => MonoEnv.pushERel env x t NONE |
65 | (env, MonoUtil.Exp.NamedE (x, n, t, eo, s)) => MonoEnv.pushENamed env x n t eo s | 101 | (env, MonoUtil.Exp.NamedE (x, n, t, eo, s)) => MonoEnv.pushENamed env x n t eo s |
66 | (env, MonoUtil.Exp.Datatype (x, n, cs)) => MonoEnv.pushDatatype env x n cs | 102 | (env, MonoUtil.Exp.Datatype (x, n, cs)) => MonoEnv.pushDatatype env x n cs |
77 NONE => NONE | 113 NONE => NONE |
78 | SOME x' => case f x' of | 114 | SOME x' => case f x' of |
79 NONE => (printer (); NONE) | 115 NONE => (printer (); NONE) |
80 | y => y | 116 | y => y |
81 | 117 |
82 (*********************) | |
83 (* General Utilities *) | |
84 (*********************) | |
85 | |
86 (* From the MLton wiki. *) | |
87 infix 3 <\ fun x <\ f = fn y => f (x, y) (* Left section *) | |
88 infix 3 \> fun f \> y = f y (* Left application *) | |
89 | |
90 fun mapFst f (x, y) = (f x, y) | |
91 | |
92 (* Option monad. *) | |
93 fun obind (x, f) = Option.mapPartial f x | |
94 fun oguard (b, x) = if b then x else NONE | |
95 fun omap f = fn SOME x => SOME (f x) | _ => NONE | |
96 fun omap2 f = fn (SOME x, SOME y) => SOME (f (x,y)) | _ => NONE | |
97 fun osequence ys = List.foldr (omap2 op::) (SOME []) ys | |
98 | |
99 fun indexOf test = | |
100 let | |
101 fun f n = | |
102 fn [] => NONE | |
103 | (x::xs) => if test x then SOME n else f (n+1) xs | |
104 in | |
105 f 0 | |
106 end | |
107 | 118 |
108 (*******************) | 119 (*******************) |
109 (* Effect Analysis *) | 120 (* Effect Analysis *) |
110 (*******************) | 121 (*******************) |
122 | |
123 (* TODO: test this. *) | |
124 fun transitiveAnalysis doVal state (decls, _) = | |
125 let | |
126 val doDecl = | |
127 fn ((DVal v, _), state) => doVal (v, state) | |
128 (* Pass over the list of values a number of times equal to its size, | |
129 making sure whatever property we're testing propagates everywhere | |
130 it should. This is analagous to the Bellman-Ford algorithm. *) | |
131 | ((DValRec vs, _), state) => | |
132 iterate (fn state => List.foldl doVal state vs) (length vs) state | |
133 | (_, state) => state | |
134 in | |
135 List.foldl doDecl state decls | |
136 end | |
111 | 137 |
112 (* Makes an exception for [EWrite] (which is recorded when caching). *) | 138 (* Makes an exception for [EWrite] (which is recorded when caching). *) |
113 fun effectful (effs : IS.set) = | 139 fun effectful (effs : IS.set) = |
114 let | 140 let |
115 val isFunction = | 141 val isFunction = |
149 in | 175 in |
150 MonoUtil.Exp.existsB {typ = fn _ => false, exp = doExp, bind = doBind} | 176 MonoUtil.Exp.existsB {typ = fn _ => false, exp = doExp, bind = doBind} |
151 end | 177 end |
152 | 178 |
153 (* TODO: test this. *) | 179 (* TODO: test this. *) |
154 fun effectfulDecls (decls, _) = | 180 fun effectfulDecls file = |
155 let | 181 transitiveAnalysis (fn ((_, name, _, e, _), effs) => |
156 fun doVal ((_, name, _, e, _), effs) = | 182 if effectful effs MonoEnv.empty e |
157 if effectful effs MonoEnv.empty e | 183 then IS.add (effs, name) |
158 then IS.add (effs, name) | 184 else effs) |
159 else effs | 185 IS.empty |
160 val doDecl = | 186 file |
161 fn ((DVal v, _), effs) => doVal (v, effs) | |
162 (* Repeat the list of declarations a number of times equal to its size, | |
163 making sure effectfulness propagates everywhere it should. This is | |
164 analagous to the Bellman-Ford algorithm. *) | |
165 | ((DValRec vs, _), effs) => | |
166 List.foldl doVal effs (List.concat (List.map (fn _ => vs) vs)) | |
167 (* ASK: any other cases? *) | |
168 | (_, effs) => effs | |
169 in | |
170 List.foldl doDecl IS.empty decls | |
171 end | |
172 | 187 |
173 | 188 |
174 (*********************************) | 189 (*********************************) |
175 (* Boolean Formula Normalization *) | 190 (* Boolean Formula Normalization *) |
176 (*********************************) | 191 (*********************************) |
1078 (* ASK: how should this (and other "=> NONE" cases) work? *) | 1093 (* ASK: how should this (and other "=> NONE" cases) work? *) |
1079 | EBinop _ => NONE | 1094 | EBinop _ => NONE |
1080 | ERecord fields => SOME (TRecord (map (fn (s, _, t) => (s, t)) fields), dummyLoc) | 1095 | ERecord fields => SOME (TRecord (map (fn (s, _, t) => (s, t)) fields), dummyLoc) |
1081 | EField (e, s) => (case typOfExp env e of | 1096 | EField (e, s) => (case typOfExp env e of |
1082 SOME (TRecord fields, _) => | 1097 SOME (TRecord fields, _) => |
1083 (case List.find (fn (s', _) => s = s') fields of | 1098 omap #2 (List.find (fn (s', _) => s = s') fields) |
1084 SOME (_, t) => SOME t | |
1085 | _ => NONE) | |
1086 | _ => NONE) | 1099 | _ => NONE) |
1087 | ECase (_, _, {result, ...}) => SOME result | 1100 | ECase (_, _, {result, ...}) => SOME result |
1088 | EStrcat _ => SOME (TFfi ("Basis", "string"), dummyLoc) | 1101 | EStrcat _ => SOME (TFfi ("Basis", "string"), dummyLoc) |
1089 | EWrite _ => SOME (TRecord [], dummyLoc) | 1102 | EWrite _ => SOME (TRecord [], dummyLoc) |
1090 | ESeq (_, e) => typOfExp env e | 1103 | ESeq (_, e) => typOfExp env e |
1412 ffiInfoRef := ffiInfo; | 1425 ffiInfoRef := ffiInfo; |
1413 file | 1426 file |
1414 end | 1427 end |
1415 | 1428 |
1416 | 1429 |
1430 (***********) | |
1431 (* Locking *) | |
1432 (***********) | |
1433 | |
1434 (* TODO: do this less evil-ly by not relying on specific FFI names, please? *) | |
1435 fun locksNeeded file = | |
1436 transitiveAnalysis | |
1437 (fn ((_, name, _, e, _), state) => | |
1438 MonoUtil.Exp.fold | |
1439 {typ = #2, | |
1440 exp = fn (EFfiApp ("Sqlcache", x, _), state as {store, flush}) => | |
1441 (case Int.fromString (String.extract (x, 5, NONE)) of | |
1442 NONE => raise Match | |
1443 | SOME index => | |
1444 if String.isPrefix "store" x | |
1445 then {store = IIMM.insert (store, name, index), flush = flush} | |
1446 else if String.isPrefix "flush" x | |
1447 then {store = store, flush = IIMM.insert (flush, name, index)} | |
1448 else state) | |
1449 | _ => state} | |
1450 state | |
1451 e) | |
1452 {store = IIMM.empty, flush = IIMM.empty} | |
1453 file | |
1454 | |
1455 fun exports (decls, _) = | |
1456 List.foldl (fn ((DExport (_, _, n, _, _, _), _), ns) => IS.add (ns, n) | |
1457 | ((DTask _, _), _) => raise Fail "Sqlcache doesn't yet support tasks." | |
1458 | (_, ns) => ns) | |
1459 IS.empty | |
1460 decls | |
1461 | |
1462 (* fun addLocking file = *) | |
1463 (* let *) | |
1464 (* val whichLocks = locksNeeded file *) | |
1465 (* val needsLocks = exports file *) | |
1466 (* in *) | |
1467 | |
1468 (* end *) | |
1469 | |
1417 (************************) | 1470 (************************) |
1418 (* Compiler Entry Point *) | 1471 (* Compiler Entry Point *) |
1419 (************************) | 1472 (************************) |
1420 | 1473 |
1421 val inlineSql = | 1474 val inlineSql = |