adam@2056: (* Copyright (c) 2014, Adam Chlipala adam@2056: * All rights reserved. adam@2056: * adam@2056: * Redistribution and use in source and binary forms, with or without adam@2056: * modification, are permitted provided that the following conditions are met: adam@2056: * adam@2056: * - Redistributions of source code must retain the above copyright notice, adam@2056: * this list of conditions and the following disclaimer. adam@2056: * - Redistributions in binary form must reproduce the above copyright notice, adam@2056: * this list of conditions and the following disclaimer in the documentation adam@2056: * and/or other materials provided with the distribution. adam@2056: * - The names of contributors may not be used to endorse or promote products adam@2056: * derived from this software without specific prior written permission. adam@2056: * adam@2056: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" adam@2056: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE adam@2056: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE adam@2056: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE ziv@2252: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR adam@2056: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF adam@2056: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS adam@2056: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN adam@2056: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) adam@2056: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE adam@2056: * POSSIBILITY OF SUCH DAMAGE. adam@2056: *) adam@2056: adam@2056: structure DbModeCheck :> DB_MODE_CHECK = struct adam@2056: adam@2056: open Mono adam@2056: adam@2056: structure IM = IntBinaryMap adam@2056: ziv@2252: fun classify (ds, ps) = adam@2056: let adam@2056: fun mergeModes (m1, m2) = adam@2056: case (m1, m2) of adam@2056: (NoDb, _) => m2 adam@2056: | (_, NoDb) => m1 adam@2056: | _ => AnyDb adam@2056: adam@2056: fun modeOf modes = adam@2056: MonoUtil.Exp.fold {typ = fn (_, dbm) => dbm, adam@2056: exp = fn (EQuery _, dbm) => mergeModes (OneQuery, dbm) adam@2056: | (EDml _, _) => AnyDb adam@2056: | (ENextval _, _) => AnyDb adam@2056: | (ESetval _, _) => AnyDb adam@2056: | (ENamed n, dbm) => adam@2056: (case IM.find (modes, n) of adam@2056: NONE => dbm adam@2056: | SOME dbm' => mergeModes (dbm, dbm')) adam@2056: | (_, dbm) => dbm} NoDb adam@2056: adam@2056: fun decl ((d, _), modes) = adam@2056: case d of adam@2056: DVal (x, n, _, e, _) => IM.insert (modes, n, modeOf modes e) adam@2056: | DValRec xes => adam@2056: let adam@2056: val mode = foldl (fn ((_, _, _, e, _), mode) => adam@2056: let adam@2056: val mode' = modeOf modes e adam@2056: in adam@2056: case mode' of adam@2056: NoDb => mode adam@2056: | _ => AnyDb adam@2056: end) NoDb xes adam@2056: in adam@2056: foldl (fn ((_, n, _, _, _), modes) => IM.insert (modes, n, mode)) modes xes adam@2056: end adam@2056: | _ => modes adam@2056: adam@2056: val modes = foldl decl IM.empty ds adam@2056: adam@2056: val (ps, modes) = ListUtil.foldlMap (fn ((n, side, _), modes) => adam@2056: case IM.find (modes, n) of adam@2056: NONE => ((n, side, AnyDb), modes) adam@2056: | SOME mode => ((n, side, mode), #1 (IM.remove (modes, n)))) adam@2056: modes ps adam@2056: adam@2056: val ps = IM.foldli (fn (n, mode, ps) => (n, ServerOnly, mode) :: ps) ps modes adam@2056: in ziv@2252: (ds, ps) adam@2056: end adam@2056: adam@2056: end ziv@2252: