annotate src/rpcify.sml @ 608:330a7de47914

Export RPC functions and push RPC calls through to Mono
author Adam Chlipala <adamc@hcoop.net>
date Sun, 15 Feb 2009 09:27:36 -0500
parents 0dd40b6bfdf3
children 56aaa1941dad
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@608 56 cpsed : int IM.map,
adamc@608 57 cps_decls : (string * int * con * exp * string) list,
adamc@608 58
adamc@608 59 exported : IS.set,
adamc@608 60 export_decls : decl list
adamc@607 61 }
adamc@607 62
adamc@607 63 fun frob file =
adamc@607 64 let
adamc@607 65 fun sideish (basis, ssids) =
adamc@607 66 U.Exp.exists {kind = fn _ => false,
adamc@607 67 con = fn _ => false,
adamc@607 68 exp = fn ENamed n => IS.member (ssids, n)
adamc@607 69 | EFfi ("Basis", x) => SS.member (basis, x)
adamc@607 70 | EFfiApp ("Basis", x, _) => SS.member (basis, x)
adamc@607 71 | _ => false}
adamc@607 72
adamc@607 73 fun whichIds basis =
adamc@607 74 let
adamc@607 75 fun decl ((d, _), ssids) =
adamc@607 76 let
adamc@607 77 val impure = sideish (basis, ssids)
adamc@607 78 in
adamc@607 79 case d of
adamc@607 80 DVal (_, n, _, e, _) => if impure e then
adamc@607 81 IS.add (ssids, n)
adamc@607 82 else
adamc@607 83 ssids
adamc@607 84 | DValRec xes => if List.exists (fn (_, _, _, e, _) => impure e) xes then
adamc@607 85 foldl (fn ((_, n, _, _, _), ssids) => IS.add (ssids, n))
adamc@607 86 ssids xes
adamc@607 87 else
adamc@607 88 ssids
adamc@607 89 | _ => ssids
adamc@607 90 end
adamc@607 91 in
adamc@607 92 foldl decl IS.empty file
adamc@607 93 end
adamc@607 94
adamc@607 95 val ssids = whichIds ssBasis
adamc@607 96 val csids = whichIds csBasis
adamc@607 97
adamc@607 98 val serverSide = sideish (ssBasis, ssids)
adamc@607 99 val clientSide = sideish (csBasis, csids)
adamc@607 100
adamc@607 101 fun exp (e, st) =
adamc@607 102 case e of
adamc@607 103 EApp (
adamc@607 104 (EApp
adamc@607 105 ((EApp ((ECApp ((ECApp ((ECApp ((EFfi ("Basis", "bind"), loc), _), _), t1), _), t2), _),
adamc@607 106 (EFfi ("Basis", "transaction_monad"), _)), _),
adamc@607 107 trans1), _),
adamc@607 108 trans2) =>
adamc@607 109 (case (serverSide trans1, clientSide trans1, serverSide trans2, clientSide trans2) of
adamc@607 110 (true, false, false, _) =>
adamc@607 111 let
adamc@607 112 fun getApp (e, args) =
adamc@607 113 case #1 e of
adamc@607 114 ENamed n => (n, args)
adamc@607 115 | EApp (e1, e2) => getApp (e1, e2 :: args)
adamc@607 116 | _ => (ErrorMsg.errorAt loc "Mixed client/server code doesn't use a named function for server part";
adamc@607 117 (0, []))
adamc@607 118
adamc@607 119 val (n, args) = getApp (trans1, [])
adamc@608 120
adamc@608 121 val (exported, export_decls) =
adamc@608 122 if IS.member (#exported st, n) then
adamc@608 123 (#exported st, #export_decls st)
adamc@608 124 else
adamc@608 125 (IS.add (#exported st, n),
adamc@608 126 (DExport (Rpc, n), loc) :: #export_decls st)
adamc@608 127
adamc@608 128 val st = {cpsed = #cpsed st,
adamc@608 129 cps_decls = #cps_decls st,
adamc@608 130
adamc@608 131 exported = exported,
adamc@608 132 export_decls = export_decls}
adamc@607 133 in
adamc@607 134 (EServerCall (n, args, trans2), st)
adamc@607 135 end
adamc@607 136 | _ => (e, st))
adamc@607 137 | _ => (e, st)
adamc@607 138
adamc@607 139 fun decl (d, st : state) =
adamc@607 140 let
adamc@607 141 val (d, st) = U.Decl.foldMap {kind = fn x => x,
adamc@607 142 con = fn x => x,
adamc@607 143 exp = exp,
adamc@607 144 decl = fn x => x}
adamc@607 145 st d
adamc@607 146 in
adamc@608 147 (List.revAppend (case #cps_decls st of
adamc@608 148 [] => [d]
adamc@608 149 | ds =>
adamc@608 150 case d of
adamc@608 151 (DValRec vis, loc) => [(DValRec (ds @ vis), loc)]
adamc@608 152 | (_, loc) => [d, (DValRec ds, loc)],
adamc@608 153 #export_decls st),
adamc@608 154 {cpsed = #cpsed st,
adamc@608 155 cps_decls = [],
adamc@608 156
adamc@608 157 exported = #exported st,
adamc@608 158 export_decls = []})
adamc@607 159 end
adamc@607 160
adamc@607 161 val (file, _) = ListUtil.foldlMapConcat decl
adamc@608 162 {cpsed = IM.empty,
adamc@608 163 cps_decls = [],
adamc@608 164
adamc@608 165 exported = IS.empty,
adamc@608 166 export_decls = []}
adamc@607 167 file
adamc@607 168 in
adamc@607 169 file
adamc@607 170 end
adamc@607 171
adamc@607 172 end