comparison src/monoize.sml @ 683:9a2c18dab11d

Expunging non-nullable rows
author Adam Chlipala <adamc@hcoop.net>
date Sun, 29 Mar 2009 13:30:01 -0400
parents 5bbb542243e8
children f0224c7f12bb
comparison
equal deleted inserted replaced
682:5bbb542243e8 683:9a2c18dab11d
163 | L.CFfi ("Basis", "sql_offset") => 163 | L.CFfi ("Basis", "sql_offset") =>
164 (L'.TFfi ("Basis", "string"), loc) 164 (L'.TFfi ("Basis", "string"), loc)
165 165
166 | L.CApp ((L.CFfi ("Basis", "sql_injectable_prim"), _), t) => 166 | L.CApp ((L.CFfi ("Basis", "sql_injectable_prim"), _), t) =>
167 (L'.TFun (mt env dtmap t, (L'.TFfi ("Basis", "string"), loc)), loc) 167 (L'.TFun (mt env dtmap t, (L'.TFfi ("Basis", "string"), loc)), loc)
168 | L.CApp ((L.CFfi ("Basis", "sql_injectable_nullable"), _), t) =>
169 (L'.TFun (mt env dtmap t, (L'.TFfi ("Basis", "string"), loc)), loc)
170 | L.CApp ((L.CFfi ("Basis", "sql_injectable"), _), t) => 168 | L.CApp ((L.CFfi ("Basis", "sql_injectable"), _), t) =>
171 (L'.TFun (mt env dtmap t, (L'.TFfi ("Basis", "string"), loc)), loc) 169 (L'.TFun (mt env dtmap t, (L'.TFfi ("Basis", "string"), loc)), loc)
172 | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_unary"), _), _), _), _) => 170 | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_unary"), _), _), _), _) =>
173 (L'.TFfi ("Basis", "string"), loc) 171 (L'.TFfi ("Basis", "string"), loc)
174 | L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_binary"), _), _), _), _), _), _) => 172 | L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_binary"), _), _), _), _), _), _) =>
246 val empty : int -> t 244 val empty : int -> t
247 245
248 val lookup : t -> foo_kind -> int -> (int -> t -> L'.decl * t) -> t * int 246 val lookup : t -> foo_kind -> int -> (int -> t -> L'.decl * t) -> t * int
249 val enter : t -> t 247 val enter : t -> t
250 val decls : t -> L'.decl list 248 val decls : t -> L'.decl list
249
250 val freshName : t -> int * t
251 end = struct 251 end = struct
252 252
253 structure M = BinaryMapFn(struct 253 structure M = BinaryMapFn(struct
254 type ord_key = foo_kind 254 type ord_key = foo_kind
255 fun compare x = 255 fun compare x =
272 map = M.empty, 272 map = M.empty,
273 decls = [] 273 decls = []
274 } 274 }
275 275
276 fun enter ({count, map, ...} : t) = {count = count, map = map, decls = []} 276 fun enter ({count, map, ...} : t) = {count = count, map = map, decls = []}
277 fun freshName {count, map, decls} = (count, {count = count + 1, map = map, decls = decls})
277 fun decls ({decls, ...} : t) = decls 278 fun decls ({decls, ...} : t) = decls
278 279
279 fun lookup (t as {count, map, decls}) k n thunk = 280 fun lookup (t as {count, map, decls}) k n thunk =
280 let 281 let
281 val im = Option.getOpt (M.find (map, k), IM.empty) 282 val im = Option.getOpt (M.find (map, k), IM.empty)
1453 (L'.EApp ((L'.ERel 2, loc), (L'.ERel 0, loc)), loc))], 1454 (L'.EApp ((L'.ERel 2, loc), (L'.ERel 0, loc)), loc))],
1454 {disc = (L'.TOption t, loc), 1455 {disc = (L'.TOption t, loc),
1455 result = s}), loc)), loc)), loc), 1456 result = s}), loc)), loc)), loc),
1456 fm) 1457 fm)
1457 end 1458 end
1458 | L.ECApp ((L.EFfi ("Basis", "sql_nullable"), _), t) =>
1459 let
1460 val t = monoType env t
1461 val s = (L'.TFfi ("Basis", "string"), loc)
1462 in
1463 ((L'.EAbs ("f",
1464 (L'.TFun (t, s), loc),
1465 (L'.TFun ((L'.TOption t, loc), s), loc),
1466 (L'.EAbs ("x",
1467 (L'.TOption t, loc),
1468 s,
1469 (L'.ECase ((L'.ERel 0, loc),
1470 [((L'.PNone t, loc),
1471 (L'.EPrim (Prim.String "NULL"), loc)),
1472 ((L'.PSome (t, (L'.PVar ("y", t), loc)), loc),
1473 (L'.EApp ((L'.ERel 2, loc), (L'.ERel 0, loc)), loc))],
1474 {disc = (L'.TOption t, loc),
1475 result = s}), loc)), loc)), loc),
1476 fm)
1477 end
1478 1459
1479 | L.ECApp ((L.EFfi ("Basis", "sql_subset"), _), _) => 1460 | L.ECApp ((L.EFfi ("Basis", "sql_subset"), _), _) =>
1480 ((L'.ERecord [], loc), fm) 1461 ((L'.ERecord [], loc), fm)
1481 | L.ECApp ((L.EFfi ("Basis", "sql_subset_all"), _), _) => 1462 | L.ECApp ((L.EFfi ("Basis", "sql_subset_all"), _), _) =>
1482 ((L'.ERecord [], loc), fm) 1463 ((L'.ERecord [], loc), fm)
2462 SOME (Env.pushENamed env x n t NONE s, 2443 SOME (Env.pushENamed env x n t NONE s,
2463 fm, 2444 fm,
2464 [(L'.DSequence s, loc), 2445 [(L'.DSequence s, loc),
2465 (L'.DVal (x, n, t', e, s), loc)]) 2446 (L'.DVal (x, n, t', e, s), loc)])
2466 end 2447 end
2467 | L.DDatabase s => SOME (env, fm, [(L'.DDatabase s, loc)]) 2448 | L.DDatabase _ => NONE
2468 | L.DCookie (x, n, t, s) => 2449 | L.DCookie (x, n, t, s) =>
2469 let 2450 let
2470 val t = (L.CFfi ("Basis", "string"), loc) 2451 val t = (L.CFfi ("Basis", "string"), loc)
2471 val t' = (L'.TFfi ("Basis", "string"), loc) 2452 val t' = (L'.TFfi ("Basis", "string"), loc)
2472 val e = (L'.EPrim (Prim.String s), loc) 2453 val e = (L'.EPrim (Prim.String s), loc)
2475 fm, 2456 fm,
2476 [(L'.DVal (x, n, t', e, s), loc)]) 2457 [(L'.DVal (x, n, t', e, s), loc)])
2477 end 2458 end
2478 end 2459 end
2479 2460
2480 fun monoize env ds = 2461 datatype expungable = Client | Channel
2462
2463 fun monoize env file =
2481 let 2464 let
2482 val p = !urlPrefix 2465 val p = !urlPrefix
2483 val () = 2466 val () =
2484 if p = "" then 2467 if p = "" then
2485 urlPrefix := "/" 2468 urlPrefix := "/"
2486 else if String.sub (p, size p - 1) <> #"/" then 2469 else if String.sub (p, size p - 1) <> #"/" then
2487 urlPrefix := p ^ "/" 2470 urlPrefix := p ^ "/"
2488 else 2471 else
2489 () 2472 ()
2490 2473
2474 val loc = E.dummySpan
2475 val client = (L'.TFfi ("Basis", "client"), loc)
2476 val unit = (L'.TRecord [], loc)
2477 fun expunger () =
2478 let
2479 val target = (L'.EFfiApp ("Basis", "sqlifyClient", [(L'.ERel 0, loc)]), loc)
2480
2481 fun doTable (tab, xts, e) =
2482 case xts of
2483 L.CRecord (_, xts) =>
2484 let
2485 val (nullable, notNullable) =
2486 foldl (fn ((x, t), st as (nullable, notNullable)) =>
2487 case #1 x of
2488 L.CName x =>
2489 (case #1 t of
2490 L.CFfi ("Basis", "client") =>
2491 (nullable, (x, Client) :: notNullable)
2492 | L.CApp ((L.CFfi ("Basis", "option"), _),
2493 (L.CFfi ("Basis", "client"), _)) =>
2494 ((x, Client) :: nullable, notNullable)
2495 | L.CApp ((L.CFfi ("Basis", "channel"), _), _) =>
2496 (nullable, (x, Channel) :: notNullable)
2497 | L.CApp ((L.CFfi ("Basis", "option"), _),
2498 (L.CApp ((L.CFfi ("Basis", "channel"), _), _), _)) =>
2499 ((x, Channel) :: nullable, notNullable)
2500 | _ => st)
2501 | _ => st) ([], []) xts
2502
2503 val e =
2504 case notNullable of
2505 [] => e
2506 | eb :: ebs =>
2507 let
2508 fun cond (x, v) =
2509 (L'.EStrcat ((L'.EPrim (Prim.String ("uw_" ^ x
2510 ^ (case v of
2511 Client => ""
2512 | Channel => " >> 32")
2513 ^ " = ")), loc),
2514 target), loc)
2515 in
2516 (L'.ESeq (
2517 (L'.EDml (foldl
2518 (fn (eb, s) =>
2519 (L'.EStrcat (s,
2520 (L'.EStrcat ((L'.EPrim (Prim.String " AND "),
2521 loc),
2522 cond eb), loc)), loc))
2523 (L'.EStrcat ((L'.EPrim (Prim.String ("DELETE FROM uw_"
2524 ^ tab
2525 ^ " WHERE ")), loc),
2526 cond eb), loc)
2527 ebs), loc),
2528 e), loc)
2529 end
2530 in
2531 e
2532 end
2533 | _ => e
2534
2535 val e = (L'.ERecord [], loc)
2536 in
2537 foldl (fn ((d, _), e) =>
2538 case d of
2539 L.DTable (_, _, xts, tab) => doTable (tab, #1 xts, e)
2540 | _ => e) e file
2541 end
2542
2491 val (_, _, ds) = List.foldl (fn (d, (env, fm, ds)) => 2543 val (_, _, ds) = List.foldl (fn (d, (env, fm, ds)) =>
2492 case monoDecl (env, fm) d of 2544 case #1 d of
2493 NONE => (env, fm, ds) 2545 L.DDatabase s =>
2494 | SOME (env, fm, ds') => 2546 let
2495 (env, 2547 val (n, fm) = Fm.freshName fm
2496 Fm.enter fm, 2548
2497 ds' @ Fm.decls fm @ ds)) 2549
2498 (env, Fm.empty (CoreUtil.File.maxName ds + 1), []) ds 2550 val d = L'.DVal ("expunger",
2551 n,
2552 (L'.TFun (client, unit), loc),
2553 (L'.EAbs ("cli", client, unit, expunger ()), loc),
2554 "expunger")
2555 in
2556 (env, Fm.enter fm, (L'.DDatabase (s, n), loc)
2557 :: (d, loc)
2558 :: ds)
2559 end
2560 | _ =>
2561 case monoDecl (env, fm) d of
2562 NONE => (env, fm, ds)
2563 | SOME (env, fm, ds') =>
2564 (env,
2565 Fm.enter fm,
2566 ds' @ Fm.decls fm @ ds))
2567 (env, Fm.empty (CoreUtil.File.maxName file + 1), []) file
2499 in 2568 in
2500 rev ds 2569 rev ds
2501 end 2570 end
2502 2571
2503 end 2572 end