annotate src/tag.sml @ 1046:a5eb8f87bc17

Better error message for link-handler conflicts
author Adam Chlipala <adamc@hcoop.net>
date Wed, 25 Nov 2009 09:03:08 -0500
parents 5fe49effbc83
children 3bc726a822fb
rev   line source
adamc@110 1 (* Copyright (c) 2008, Adam Chlipala
adamc@110 2 * All rights reserved.
adamc@110 3 *
adamc@110 4 * Redistribution and use in source and binary forms, with or without
adamc@110 5 * modification, are permitted provided that the following conditions are met:
adamc@110 6 *
adamc@110 7 * - Redistributions of source code must retain the above copyright notice,
adamc@110 8 * this list of conditions and the following disclaimer.
adamc@110 9 * - Redistributions in binary form must reproduce the above copyright notice,
adamc@110 10 * this list of conditions and the following disclaimer in the documentation
adamc@110 11 * and/or other materials provided with the distribution.
adamc@110 12 * - The names of contributors may not be used to endorse or promote products
adamc@110 13 * derived from this software without specific prior written permission.
adamc@110 14 *
adamc@110 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
adamc@110 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
adamc@110 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
adamc@110 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
adamc@110 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
adamc@110 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
adamc@110 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
adamc@110 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
adamc@110 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
adamc@110 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
adamc@110 25 * POSSIBILITY OF SUCH DAMAGE.
adamc@110 26 *)
adamc@110 27
adamc@110 28 structure Tag :> TAG = struct
adamc@110 29
adamc@110 30 open Core
adamc@110 31
adamc@110 32 structure U = CoreUtil
adamc@110 33 structure E = CoreEnv
adamc@110 34
adamc@110 35 structure IM = IntBinaryMap
adamc@112 36 structure SM = BinaryMapFn(struct
adamc@112 37 type ord_key = string
adamc@112 38 val compare = String.compare
adamc@112 39 end)
adamc@110 40
adamc@110 41 fun kind (k, s) = (k, s)
adamc@110 42 fun con (c, s) = (c, s)
adamc@110 43
adamc@1046 44 fun both (loc, f) = (ErrorMsg.errorAt loc ("Function " ^ f ^ " needed for both a link and a form");
adamc@1046 45 TextIO.output (TextIO.stdErr,
adamc@1046 46 "Make sure that the signature of the containing module hides any form handlers.\n"))
adamc@1046 47
adamc@112 48 fun exp env (e, s) =
adamc@110 49 case e of
adamc@110 50 EApp (
adamc@110 51 (EApp (
adamc@110 52 (EApp (
adamc@721 53 (EApp (
adamc@110 54 (ECApp (
adamc@110 55 (ECApp (
adamc@110 56 (ECApp (
adamc@140 57 (ECApp (
adamc@140 58 (ECApp (
adamc@140 59 (ECApp (
adamc@140 60 (ECApp (
adamc@721 61 (ECApp (
adamc@721 62 (EFfi ("Basis", "tag"),
adamc@721 63 loc), given), _), absent), _), outer), _), inner), _),
adamc@721 64 useOuter), _), useInner), _), bindOuter), _), bindInner), _),
adamc@721 65 class), _),
adamc@110 66 attrs), _),
adamc@110 67 tag), _),
adamc@110 68 xml) =>
adamc@110 69 (case attrs of
adamc@110 70 (ERecord xets, _) =>
adamc@110 71 let
adamc@110 72 val (xets, s) =
adamc@112 73 ListUtil.foldlMap (fn ((x, e, t), (count, tags, byTag, newTags)) =>
adamc@143 74 let
adamc@144 75 fun tagIt (ek, newAttr) =
adamc@143 76 let
adamc@143 77 fun unravel (e, _) =
adamc@143 78 case e of
adamc@143 79 ENamed n => (n, [])
adamc@143 80 | EApp (e1, e2) =>
adamc@143 81 let
adamc@143 82 val (n, es) = unravel e1
adamc@143 83 in
adamc@143 84 (n, es @ [e2])
adamc@143 85 end
adamc@143 86 | _ => (ErrorMsg.errorAt loc "Invalid link expression";
adamc@143 87 (0, []))
adamc@110 88
adamc@143 89 val (f, args) = unravel e
adamc@112 90
adamc@143 91 val (cn, count, tags, newTags) =
adamc@143 92 case IM.find (tags, f) of
adamc@143 93 NONE =>
adamc@143 94 (count, count + 1, IM.insert (tags, f, count),
adamc@144 95 (ek, f, count) :: newTags)
adamc@143 96 | SOME cn => (cn, count, tags, newTags)
adamc@143 97
adamc@143 98 val (_, _, _, s) = E.lookupENamed env f
adamc@112 99
adamc@143 100 val byTag = case SM.find (byTag, s) of
adamc@144 101 NONE => SM.insert (byTag, s, (ek, f))
adamc@144 102 | SOME (ek', f') =>
adamc@143 103 (if f = f' then
adamc@143 104 ()
adamc@143 105 else
adamc@143 106 ErrorMsg.errorAt loc
adamc@143 107 ("Duplicate HTTP tag "
adamc@143 108 ^ s);
adamc@144 109 if ek = ek' then
adamc@144 110 ()
adamc@144 111 else
adamc@1046 112 both (loc, s);
adamc@143 113 byTag)
adamc@143 114
adamc@143 115 val e = (EClosure (cn, args), loc)
adamc@143 116 val t = (CFfi ("Basis", "string"), loc)
adamc@143 117 in
adamc@143 118 (((CName newAttr, loc), e, t),
adamc@143 119 (count, tags, byTag, newTags))
adamc@143 120 end
adamc@143 121 in
adamc@143 122 case x of
adamc@907 123 (CName "Link", _) => tagIt (Link, "Link")
adamc@731 124 | (CName "Action", _) => tagIt (Action ReadWrite, "Action")
adamc@143 125 | _ => ((x, e, t), (count, tags, byTag, newTags))
adamc@143 126 end)
adamc@110 127 s xets
adamc@110 128 in
adamc@110 129 (EApp (
adamc@110 130 (EApp (
adamc@110 131 (EApp (
adamc@721 132 (EApp (
adamc@110 133 (ECApp (
adamc@110 134 (ECApp (
adamc@110 135 (ECApp (
adamc@140 136 (ECApp (
adamc@140 137 (ECApp (
adamc@140 138 (ECApp (
adamc@140 139 (ECApp (
adamc@721 140 (ECApp (
adamc@721 141 (EFfi ("Basis", "tag"),
adamc@721 142 loc), given), loc), absent), loc), outer), loc), inner), loc),
adamc@721 143 useOuter), loc), useInner), loc), bindOuter), loc), bindInner), loc),
adamc@721 144 class), loc),
adamc@110 145 (ERecord xets, loc)), loc),
adamc@110 146 tag), loc),
adamc@110 147 xml), s)
adamc@110 148 end
adamc@110 149 | _ => (ErrorMsg.errorAt loc "Attribute record is too complex";
adamc@110 150 (e, s)))
adamc@110 151
adamc@110 152 | _ => (e, s)
adamc@110 153
adamc@110 154 fun decl (d, s) = (d, s)
adamc@110 155
adamc@110 156 fun tag file =
adamc@110 157 let
adamc@179 158 val count = U.File.maxName file
adamc@110 159
adamc@112 160 fun doDecl (d as (d', loc), (env, count, tags, byTag)) =
adamc@112 161 case d' of
adamc@144 162 DExport (ek, n) =>
adamc@112 163 let
adamc@112 164 val (_, _, _, s) = E.lookupENamed env n
adamc@112 165 in
adamc@112 166 case SM.find (byTag, s) of
adamc@112 167 NONE => ([d], (env, count, tags, byTag))
adamc@144 168 | SOME (ek', n') =>
adamc@144 169 (if ek = ek' then
adamc@144 170 ()
adamc@144 171 else
adamc@1046 172 both (loc, s);
adamc@144 173 ([], (env, count, tags, byTag)))
adamc@112 174 end
adamc@112 175 | _ =>
adamc@112 176 let
adamc@126 177 val env' = E.declBinds env d
adamc@126 178 val env'' = case d' of
adamc@126 179 DValRec _ => env'
adamc@126 180 | _ => env
adamc@126 181
adamc@112 182 val (d, (count, tags, byTag, newTags)) =
adamc@112 183 U.Decl.foldMap {kind = kind,
adamc@112 184 con = con,
adamc@126 185 exp = exp env'',
adamc@112 186 decl = decl}
adamc@112 187 (count, tags, byTag, []) d
adamc@110 188
adamc@126 189 val env = env'
adamc@110 190
adamc@126 191 val newDs = map
adamc@144 192 (fn (ek, f, cn) =>
adamc@112 193 let
adamc@492 194 val unit = (TRecord (CRecord ((KType, loc), []), loc), loc)
adamc@492 195
adamc@112 196 fun unravel (all as (t, _)) =
adamc@112 197 case t of
adamc@112 198 TFun (dom, ran) =>
adamc@112 199 let
adamc@112 200 val (args, result) = unravel ran
adamc@112 201 in
adamc@112 202 (dom :: args, result)
adamc@112 203 end
adamc@112 204 | _ => ([], all)
adamc@110 205
adamc@112 206 val (fnam, t, _, tag) = E.lookupENamed env f
adamc@112 207 val (args, result) = unravel t
adamc@110 208
adamc@119 209 val (abs, t) =
adamc@119 210 case args of
adamc@119 211 [] =>
adamc@119 212 let
adamc@492 213 val app = (EApp ((ENamed f, loc), (ERecord [], loc)), loc)
adamc@492 214 val body = (EWrite app, loc)
adamc@119 215 in
adamc@492 216 (body,
adamc@119 217 (TFun (unit, unit), loc))
adamc@119 218 end
adamc@119 219 | _ =>
adamc@119 220 let
adamc@119 221 val (app, _) = foldl (fn (t, (app, n)) =>
adamc@119 222 ((EApp (app, (ERel n, loc)), loc),
adamc@119 223 n - 1))
adamc@119 224 ((ENamed f, loc), length args - 1) args
adamc@280 225 val app = (EApp (app, (ERecord [], loc)), loc)
adamc@119 226 val body = (EWrite app, loc)
adamc@280 227 val t = (TFun (unit, unit), loc)
adamc@119 228 val (abs, _, t) = foldr (fn (t, (abs, n, rest)) =>
adamc@119 229 ((EAbs ("x" ^ Int.toString n,
adamc@119 230 t,
adamc@119 231 rest,
adamc@119 232 abs), loc),
adamc@119 233 n + 1,
adamc@119 234 (TFun (t, rest), loc)))
adamc@280 235 (body, 0, t) args
adamc@119 236 in
adamc@119 237 (abs, t)
adamc@119 238 end
adamc@112 239 in
adamc@126 240 (("wrap_" ^ fnam, cn, t, abs, tag),
adamc@144 241 (DExport (ek, cn), loc))
adamc@112 242 end) newTags
adamc@126 243
adamc@126 244 val (newVals, newExports) = ListPair.unzip newDs
adamc@126 245
adamc@126 246 val ds = case d of
adamc@126 247 (DValRec vis, _) => [(DValRec (vis @ newVals), loc)]
adamc@126 248 | _ => map (fn vi => (DVal vi, loc)) newVals @ [d]
adamc@112 249 in
adamc@126 250 (ds @ newExports, (env, count, tags, byTag))
adamc@112 251 end
adamc@110 252
adamc@112 253 val (file, _) = ListUtil.foldlMapConcat doDecl (CoreEnv.empty, count+1, IM.empty, SM.empty) file
adamc@110 254 in
adamc@110 255 file
adamc@110 256 end
adamc@110 257
adamc@110 258 end