annotate src/rpcify.sml @ 607:0dd40b6bfdf3

Start of RPCification
author Adam Chlipala <adamc@hcoop.net>
date Sat, 14 Feb 2009 14:07:56 -0500
parents
children 330a7de47914
rev   line source
adamc@607 1 (* Copyright (c) 2009, Adam Chlipala
adamc@607 2 * All rights reserved.
adamc@607 3 *
adamc@607 4 * Redistribution and use in source and binary forms, with or without
adamc@607 5 * modification, are permitted provided that the following conditions are met:
adamc@607 6 *
adamc@607 7 * - Redistributions of source code must retain the above copyright notice,
adamc@607 8 * this list of conditions and the following disclaimer.
adamc@607 9 * - Redistributions in binary form must reproduce the above copyright notice,
adamc@607 10 * this list of conditions and the following disclaimer in the documentation
adamc@607 11 * and/or other materials provided with the distribution.
adamc@607 12 * - The names of contributors may not be used to endorse or promote products
adamc@607 13 * derived from this software without specific prior written permission.
adamc@607 14 *
adamc@607 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
adamc@607 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
adamc@607 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
adamc@607 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
adamc@607 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
adamc@607 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
adamc@607 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
adamc@607 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
adamc@607 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
adamc@607 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
adamc@607 25 * POSSIBILITY OF SUCH DAMAGE.
adamc@607 26 *)
adamc@607 27
adamc@607 28 structure Rpcify :> RPCIFY = struct
adamc@607 29
adamc@607 30 open Core
adamc@607 31
adamc@607 32 structure U = CoreUtil
adamc@607 33 structure E = CoreEnv
adamc@607 34
adamc@607 35 structure IS = IntBinarySet
adamc@607 36 structure IM = IntBinaryMap
adamc@607 37
adamc@607 38 structure SS = BinarySetFn(struct
adamc@607 39 type ord_key = string
adamc@607 40 val compare = String.compare
adamc@607 41 end)
adamc@607 42
adamc@607 43 val ssBasis = SS.addList (SS.empty,
adamc@607 44 ["requestHeader",
adamc@607 45 "query",
adamc@607 46 "dml",
adamc@607 47 "nextval"])
adamc@607 48
adamc@607 49 val csBasis = SS.addList (SS.empty,
adamc@607 50 ["source",
adamc@607 51 "get",
adamc@607 52 "set",
adamc@607 53 "alert"])
adamc@607 54
adamc@607 55 type state = {
adamc@607 56 exps : int IM.map,
adamc@607 57 decls : (string * int * con * exp * string) list
adamc@607 58 }
adamc@607 59
adamc@607 60 fun frob file =
adamc@607 61 let
adamc@607 62 fun sideish (basis, ssids) =
adamc@607 63 U.Exp.exists {kind = fn _ => false,
adamc@607 64 con = fn _ => false,
adamc@607 65 exp = fn ENamed n => IS.member (ssids, n)
adamc@607 66 | EFfi ("Basis", x) => SS.member (basis, x)
adamc@607 67 | EFfiApp ("Basis", x, _) => SS.member (basis, x)
adamc@607 68 | _ => false}
adamc@607 69
adamc@607 70 fun whichIds basis =
adamc@607 71 let
adamc@607 72 fun decl ((d, _), ssids) =
adamc@607 73 let
adamc@607 74 val impure = sideish (basis, ssids)
adamc@607 75 in
adamc@607 76 case d of
adamc@607 77 DVal (_, n, _, e, _) => if impure e then
adamc@607 78 IS.add (ssids, n)
adamc@607 79 else
adamc@607 80 ssids
adamc@607 81 | DValRec xes => if List.exists (fn (_, _, _, e, _) => impure e) xes then
adamc@607 82 foldl (fn ((_, n, _, _, _), ssids) => IS.add (ssids, n))
adamc@607 83 ssids xes
adamc@607 84 else
adamc@607 85 ssids
adamc@607 86 | _ => ssids
adamc@607 87 end
adamc@607 88 in
adamc@607 89 foldl decl IS.empty file
adamc@607 90 end
adamc@607 91
adamc@607 92 val ssids = whichIds ssBasis
adamc@607 93 val csids = whichIds csBasis
adamc@607 94
adamc@607 95 val serverSide = sideish (ssBasis, ssids)
adamc@607 96 val clientSide = sideish (csBasis, csids)
adamc@607 97
adamc@607 98 fun exp (e, st) =
adamc@607 99 case e of
adamc@607 100 EApp (
adamc@607 101 (EApp
adamc@607 102 ((EApp ((ECApp ((ECApp ((ECApp ((EFfi ("Basis", "bind"), loc), _), _), t1), _), t2), _),
adamc@607 103 (EFfi ("Basis", "transaction_monad"), _)), _),
adamc@607 104 trans1), _),
adamc@607 105 trans2) =>
adamc@607 106 (case (serverSide trans1, clientSide trans1, serverSide trans2, clientSide trans2) of
adamc@607 107 (true, false, false, _) =>
adamc@607 108 let
adamc@607 109 fun getApp (e, args) =
adamc@607 110 case #1 e of
adamc@607 111 ENamed n => (n, args)
adamc@607 112 | EApp (e1, e2) => getApp (e1, e2 :: args)
adamc@607 113 | _ => (ErrorMsg.errorAt loc "Mixed client/server code doesn't use a named function for server part";
adamc@607 114 (0, []))
adamc@607 115
adamc@607 116 val (n, args) = getApp (trans1, [])
adamc@607 117 in
adamc@607 118 (EServerCall (n, args, trans2), st)
adamc@607 119 end
adamc@607 120 | _ => (e, st))
adamc@607 121 | _ => (e, st)
adamc@607 122
adamc@607 123 fun decl (d, st : state) =
adamc@607 124 let
adamc@607 125 val (d, st) = U.Decl.foldMap {kind = fn x => x,
adamc@607 126 con = fn x => x,
adamc@607 127 exp = exp,
adamc@607 128 decl = fn x => x}
adamc@607 129 st d
adamc@607 130 in
adamc@607 131 (case #decls st of
adamc@607 132 [] => [d]
adamc@607 133 | ds =>
adamc@607 134 case d of
adamc@607 135 (DValRec vis, loc) => [(DValRec (ds @ vis), loc)]
adamc@607 136 | (_, loc) => [(DValRec ds, loc), d],
adamc@607 137 {decls = [],
adamc@607 138 exps = #exps st})
adamc@607 139 end
adamc@607 140
adamc@607 141 val (file, _) = ListUtil.foldlMapConcat decl
adamc@607 142 {decls = [],
adamc@607 143 exps = IM.empty}
adamc@607 144 file
adamc@607 145 in
adamc@607 146 file
adamc@607 147 end
adamc@607 148
adamc@607 149 end