annotate src/marshalcheck.sml @ 758:8323c1beef2e

Subforms type-checks; lists urlified and unurlified
author Adam Chlipala <adamc@hcoop.net>
date Thu, 30 Apr 2009 11:48:56 -0400
parents 4bb7e1c0550a
children a28982de5645
rev   line source
adamc@680 1 (* Copyright (c) 2009, Adam Chlipala
adamc@680 2 * All rights reserved.
adamc@680 3 *
adamc@680 4 * Redistribution and use in source and binary forms, with or without
adamc@680 5 * modification, are permitted provided that the following conditions are met:
adamc@680 6 *
adamc@680 7 * - Redistributions of source code must retain the above copyright notice,
adamc@680 8 * this list of conditions and the following disclaimer.
adamc@680 9 * - Redistributions in binary form must reproduce the above copyright notice,
adamc@680 10 * this list of conditions and the following disclaimer in the documentation
adamc@680 11 * and/or other materials provided with the distribution.
adamc@680 12 * - The names of contributors may not be used to endorse or promote products
adamc@680 13 * derived from this software without specific prior written permission.
adamc@680 14 *
adamc@680 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
adamc@680 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
adamc@680 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
adamc@680 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
adamc@680 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
adamc@680 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
adamc@680 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
adamc@680 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
adamc@680 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
adamc@680 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
adamc@680 25 * POSSIBILITY OF SUCH DAMAGE.
adamc@680 26 *)
adamc@680 27
adamc@680 28 structure MarshalCheck :> MARSHAL_CHECK = struct
adamc@680 29
adamc@680 30 open Core
adamc@680 31
adamc@680 32 structure U = CoreUtil
adamc@680 33 structure E = ErrorMsg
adamc@680 34
adamc@680 35 structure PK = struct
adamc@680 36 open Order
adamc@680 37 type ord_key = string * string
adamc@680 38 fun compare ((m1, x1), (m2, x2)) =
adamc@680 39 join (String.compare (m1, m2),
adamc@680 40 fn () => String.compare (x1, x2))
adamc@680 41 end
adamc@680 42
adamc@680 43 structure PS = BinarySetFn(PK)
adamc@680 44 structure PS = struct
adamc@680 45 open PS
adamc@680 46 fun toString' (m, x) = m ^ "." ^ x
adamc@680 47 fun toString set =
adamc@680 48 case PS.listItems set of
adamc@680 49 [] => "{}"
adamc@680 50 | [x] => toString' x
adamc@680 51 | x :: xs => List.foldl (fn (x, s) => s ^ ", " ^ toString' x) (toString' x) xs
adamc@680 52 end
adamc@680 53
adamc@680 54 structure IM = IntBinaryMap
adamc@680 55
adamc@680 56 val clientToServer = [("Basis", "int"),
adamc@680 57 ("Basis", "float"),
adamc@680 58 ("Basis", "string"),
adamc@680 59 ("Basis", "time"),
adamc@739 60 ("Basis", "file"),
adamc@680 61 ("Basis", "unit"),
adamc@692 62 ("Basis", "option"),
adamc@758 63 ("Basis", "list"),
adamc@692 64 ("Basis", "bool")]
adamc@680 65
adamc@680 66 val clientToServer = PS.addList (PS.empty, clientToServer)
adamc@680 67
adamc@680 68 fun check file =
adamc@680 69 let
adamc@680 70 fun kind (_, st) = st
adamc@680 71
adamc@680 72 fun con cmap (c, st) =
adamc@680 73 case c of
adamc@680 74 CFfi mx =>
adamc@680 75 if PS.member (clientToServer, mx) then
adamc@680 76 st
adamc@680 77 else
adamc@680 78 PS.add (st, mx)
adamc@680 79 | CNamed n =>
adamc@680 80 (case IM.find (cmap, n) of
adamc@680 81 NONE => st
adamc@680 82 | SOME st' => PS.union (st, st'))
adamc@680 83 | _ => st
adamc@680 84
adamc@680 85 fun sins cmap = U.Con.fold {kind = kind, con = con cmap} PS.empty
adamc@680 86 in
adamc@680 87 ignore (foldl (fn ((d, _), (cmap, emap)) =>
adamc@680 88 case d of
adamc@680 89 DCon (_, n, _, c) => (IM.insert (cmap, n, sins cmap c), emap)
adamc@680 90 | DDatatype (_, n, _, xncs) =>
adamc@680 91 (IM.insert (cmap, n, foldl (fn ((_, _, co), s) =>
adamc@680 92 case co of
adamc@680 93 NONE => s
adamc@680 94 | SOME c => PS.union (s, sins cmap c))
adamc@680 95 PS.empty xncs),
adamc@680 96 emap)
adamc@680 97
adamc@680 98 | DVal (_, n, t, _, tag) => (cmap, IM.insert (emap, n, (t, tag)))
adamc@680 99 | DValRec vis => (cmap,
adamc@680 100 foldl (fn ((_, n, t, _, tag), emap) => IM.insert (emap, n, (t, tag)))
adamc@680 101 emap vis)
adamc@680 102
adamc@680 103 | DExport (_, n) =>
adamc@680 104 (case IM.find (emap, n) of
adamc@680 105 NONE => raise Fail "MarshalCheck: Unknown export"
adamc@680 106 | SOME (t, tag) =>
adamc@680 107 let
adamc@680 108 fun makeS (t, _) =
adamc@680 109 case t of
adamc@680 110 TFun (dom, ran) => PS.union (sins cmap dom, makeS ran)
adamc@680 111 | _ => PS.empty
adamc@680 112 val s = makeS t
adamc@680 113 in
adamc@680 114 if PS.isEmpty s then
adamc@680 115 ()
adamc@680 116 else
adamc@680 117 E.error ("Input to exported function '"
adamc@680 118 ^ tag ^ "' involves one or more disallowed types: "
adamc@680 119 ^ PS.toString s);
adamc@680 120 (cmap, emap)
adamc@680 121 end)
adamc@680 122
adamc@680 123 | DCookie (_, _, t, tag) =>
adamc@680 124 let
adamc@680 125 val s = sins cmap t
adamc@680 126 in
adamc@680 127 if PS.isEmpty s then
adamc@680 128 ()
adamc@680 129 else
adamc@680 130 E.error ("Cookie '" ^ tag ^ "' includes one or more disallowed types: "
adamc@680 131 ^ PS.toString s);
adamc@680 132 (cmap, emap)
adamc@680 133 end
adamc@680 134
adamc@680 135 | _ => (cmap, emap))
adamc@680 136 (IM.empty, IM.empty) file)
adamc@680 137 end
adamc@680 138
adamc@680 139 end