Mercurial > urweb
diff src/rpcify.sml @ 908:ed06e25c70ef
Convert to requiring explicit 'rpc' marker
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sat, 22 Aug 2009 12:55:18 -0400 |
parents | a28982de5645 |
children | 2a50da66ffd8 |
line wrap: on
line diff
--- a/src/rpcify.sml Tue Aug 11 12:01:54 2009 -0400 +++ b/src/rpcify.sml Sat Aug 22 12:55:18 2009 -0400 @@ -40,67 +40,22 @@ val compare = String.compare end) -fun multiLiftExpInExp n e = - if n = 0 then - e - else - multiLiftExpInExp (n - 1) (E.liftExpInExp 0 e) - type state = { - cpsed : int IM.map, - cpsed_range : con IM.map, - cps_decls : (string * int * con * exp * string) list, - exported : IS.set, - export_decls : decl list, - - maxName : int + export_decls : decl list } fun frob file = let - fun sideish (basis, ssids) e = - U.Exp.exists {kind = fn _ => false, - con = fn _ => false, - exp = fn ENamed n => IS.member (ssids, n) - | EFfi x => basis x - | EFfiApp (m, x, _) => basis (m, x) - | _ => false} - (U.Exp.map {kind = fn x => x, - con = fn x => x, - exp = fn ERecord _ => ERecord [] - | x => x} e) - - fun whichIds basis = - let - fun decl ((d, _), ssids) = - let - val impure = sideish (basis, ssids) - in - case d of - DVal (_, n, _, e, _) => if impure e then - IS.add (ssids, n) - else - ssids - | DValRec xes => if List.exists (fn (_, _, _, e, _) => impure e) xes then - foldl (fn ((_, n, _, _, _), ssids) => IS.add (ssids, n)) - ssids xes - else - ssids - | _ => ssids - end - in - foldl decl IS.empty file - end - - val ssids = whichIds Settings.isServerOnly - val csids = whichIds Settings.isClientOnly - - fun sideish' (basis, ids) extra = - sideish (basis, IM.foldli (fn (id, _, ids) => IS.add (ids, id)) ids extra) - - val serverSide = sideish' (Settings.isServerOnly, ssids) - val clientSide = sideish' (Settings.isClientOnly, csids) + val rpcBaseIds = foldl (fn ((d, _), rpcIds) => + case d of + DVal (_, n, _, (EFfi ("Basis", "rpc"), _), _) => IS.add (rpcIds, n) + | DVal (_, n, _, (ENamed n', _), _) => if IS.member (rpcIds, n') then + IS.add (rpcIds, n) + else + rpcIds + | _ => rpcIds) + IS.empty file val tfuncs = foldl (fn ((d, _), tfuncs) => @@ -134,312 +89,50 @@ fun exp (e, st) = let fun getApp (e', args) = - let - val loc = #2 e' - in - case #1 e' of - ENamed n => (n, args) - | EApp (e1, e2) => getApp (e1, e2 :: args) - | _ => (ErrorMsg.errorAt loc "Mixed client/server code doesn't use a named function for server part"; - (*Print.prefaces "Bad" [("e", CorePrint.p_exp CoreEnv.empty (e, ErrorMsg.dummySpan))];*) - (0, [])) - end + case e' of + ENamed n => SOME (n, args) + | EApp (e1, e2) => getApp (#1 e1, e2 :: args) + | _ => NONE - fun newRpc (trans1, trans2, st : state) = - let - val loc = #2 trans1 + fun newRpc (trans : exp, st : state) = + case getApp (#1 trans, []) of + NONE => (ErrorMsg.errorAt (#2 trans) + "RPC code doesn't use a named function or transaction"; + (#1 trans, st)) + | SOME (n, args) => + case IM.find (tfuncs, n) of + NONE => ((*Print.prefaces "BAD" [("e", CorePrint.p_exp CoreEnv.empty (e, loc))];*) + raise Fail ("Rpcify: Undetected transaction function " ^ Int.toString n)) + | SOME (_, _, ran, _) => + let + val loc = #2 trans - val (n, args) = getApp (trans1, []) + val (exported, export_decls) = + if IS.member (#exported st, n) then + (#exported st, #export_decls st) + else + (IS.add (#exported st, n), + (DExport (Rpc ReadWrite, n), loc) :: #export_decls st) - val (exported, export_decls) = - if IS.member (#exported st, n) then - (#exported st, #export_decls st) - else - (IS.add (#exported st, n), - (DExport (Rpc ReadWrite, n), loc) :: #export_decls st) + val st = {exported = exported, + export_decls = export_decls} - val st = {cpsed = #cpsed st, - cpsed_range = #cpsed_range st, - cps_decls = #cps_decls st, - - exported = exported, - export_decls = export_decls, - - maxName = #maxName st} - - val ran = - case IM.find (tfuncs, n) of - NONE => ((*Print.prefaces "BAD" [("e", CorePrint.p_exp CoreEnv.empty (e, loc))];*) - raise Fail ("Rpcify: Undetected transaction function " ^ Int.toString n)) - | SOME (_, _, ran, _) => ran - - val e' = EServerCall (n, args, trans2, ran) - in - (e', st) - end - - fun newCps (t1, t2, trans1, trans2, st) = - let - val loc = #2 trans1 - - val (n, args) = getApp (trans1, []) - - fun makeCall n' = - let - val e = (ENamed n', loc) - val e = (EApp (e, trans2), loc) + val k = (ECApp ((EFfi ("Basis", "return"), loc), + (CFfi ("Basis", "transaction"), loc)), loc) + val k = (ECApp (k, ran), loc) + val k = (EApp (k, (EFfi ("Basis", "transaction_monad"), loc)), loc) + val e' = EServerCall (n, args, k, ran, ran) in - #1 (foldl (fn (arg, e) => (EApp (e, arg), loc)) e args) + (e', st) end - in - case IM.find (#cpsed_range st, n) of - SOME kdom => - (case args of - [] => raise Fail "Rpcify: cps'd function lacks first argument" - | ke :: args => - let - val ke' = (EFfi ("Basis", "bind"), loc) - val ke' = (ECApp (ke', (CFfi ("Basis", "transaction"), loc)), loc) - val ke' = (ECApp (ke', kdom), loc) - val ke' = (ECApp (ke', t2), loc) - val ke' = (EApp (ke', (EFfi ("Basis", "transaction_monad"), loc)), loc) - val ke' = (EApp (ke', (EApp (E.liftExpInExp 0 ke, (ERel 0, loc)), loc)), loc) - val ke' = (EApp (ke', E.liftExpInExp 0 trans2), loc) - val ke' = (EAbs ("x", kdom, - (CApp ((CFfi ("Basis", "transaction"), loc), t2), loc), - ke'), loc) - - val e' = (ENamed n, loc) - val e' = (EApp (e', ke'), loc) - val e' = foldl (fn (arg, e') => (EApp (e', arg), loc)) e' args - val (e', st) = doExp (e', st) - in - (#1 e', st) - end) - | NONE => - case IM.find (#cpsed st, n) of - SOME n' => (makeCall n', st) - | NONE => - let - val (name, fargs, ran, e) = - case IM.find (tfuncs, n) of - NONE => (Print.prefaces "BAD" [("e", - CorePrint.p_exp CoreEnv.empty (e, loc))]; - raise Fail "Rpcify: Undetected transaction function [2]") - | SOME x => x - - val n' = #maxName st - - val st = {cpsed = IM.insert (#cpsed st, n, n'), - cpsed_range = IM.insert (#cpsed_range st, n', ran), - cps_decls = #cps_decls st, - exported = #exported st, - export_decls = #export_decls st, - maxName = n' + 1} - - val unit = (TRecord (CRecord ((KType, loc), []), loc), loc) - val body = (EFfi ("Basis", "bind"), loc) - val body = (ECApp (body, (CFfi ("Basis", "transaction"), loc)), loc) - val body = (ECApp (body, t1), loc) - val body = (ECApp (body, unit), loc) - val body = (EApp (body, (EFfi ("Basis", "transaction_monad"), loc)), loc) - val body = (EApp (body, e), loc) - val body = (EApp (body, (ERel (length args), loc)), loc) - val bt = (CApp ((CFfi ("Basis", "transaction"), loc), unit), loc) - val (body, bt) = foldr (fn ((x, t), (body, bt)) => - ((EAbs (x, t, bt, body), loc), - (TFun (t, bt), loc))) - (body, bt) fargs - val kt = (TFun (ran, (CApp ((CFfi ("Basis", "transaction"), loc), - unit), - loc)), loc) - val body = (EAbs ("k", kt, bt, body), loc) - val bt = (TFun (kt, bt), loc) - - val (body, st) = doExp (body, st) - - val vi = (name ^ "_cps", - n', - bt, - body, - "") - - val st = {cpsed = #cpsed st, - cpsed_range = #cpsed_range st, - cps_decls = vi :: #cps_decls st, - exported = #exported st, - export_decls = #export_decls st, - maxName = #maxName st} - in - (makeCall n', st) - end - end - - fun dummyK loc = - let - val unit = (TRecord (CRecord ((KType, loc), []), loc), loc) - - val k = (EFfi ("Basis", "return"), loc) - val k = (ECApp (k, (CFfi ("Basis", "transaction"), loc)), loc) - val k = (ECApp (k, unit), loc) - val k = (EApp (k, (EFfi ("Basis", "transaction_monad"), loc)), loc) - val k = (EApp (k, (ERecord [], loc)), loc) - in - (EAbs ("_", unit, unit, k), loc) - end in case e of - EApp ( - (EApp - ((EApp ((ECApp ((ECApp ((ECApp ((EFfi ("Basis", "bind"), loc), _), _), t1), _), t2), _), - (EFfi ("Basis", "transaction_monad"), _)), _), - (ECase (ed, pes, {disc, ...}), _)), _), - trans2) => - let - val e' = (EFfi ("Basis", "bind"), loc) - val e' = (ECApp (e', (CFfi ("Basis", "transaction"), loc)), loc) - val e' = (ECApp (e', t1), loc) - val e' = (ECApp (e', t2), loc) - val e' = (EApp (e', (EFfi ("Basis", "transaction_monad"), loc)), loc) - - val (pes, st) = ListUtil.foldlMap (fn ((p, e), st) => - let - val e' = (EApp (e', e), loc) - val e' = (EApp (e', - multiLiftExpInExp (E.patBindsN p) - trans2), loc) - val (e', st) = doExp (e', st) - in - ((p, e'), st) - end) st pes - in - (ECase (ed, pes, {disc = disc, - result = (CApp ((CFfi ("Basis", "transaction"), loc), t2), loc)}), - st) - end - - | EApp ( - (EApp - ((EApp ((ECApp ((ECApp ((ECApp ((EFfi ("Basis", "bind"), loc), _), _), t1), _), t2), _), - (EFfi ("Basis", "transaction_monad"), _)), _), - (EServerCall (n, es, ke, t), _)), _), - trans2) => - let - val e' = (EFfi ("Basis", "bind"), loc) - val e' = (ECApp (e', (CFfi ("Basis", "transaction"), loc)), loc) - val e' = (ECApp (e', t), loc) - val e' = (ECApp (e', t2), loc) - val e' = (EApp (e', (EFfi ("Basis", "transaction_monad"), loc)), loc) - val e' = (EApp (e', (EApp (E.liftExpInExp 0 ke, (ERel 0, loc)), loc)), loc) - val e' = (EApp (e', E.liftExpInExp 0 trans2), loc) - val e' = (EAbs ("x", t, t2, e'), loc) - val e' = (EServerCall (n, es, e', t), loc) - val (e', st) = doExp (e', st) - in - (#1 e', st) - end - - | EApp ( - (EApp - ((EApp ((ECApp ((ECApp ((ECApp ((EFfi ("Basis", "bind"), loc), _), _), _), _), t3), _), - (EFfi ("Basis", "transaction_monad"), _)), _), - (EApp ((EApp - ((EApp ((ECApp ((ECApp ((ECApp ((EFfi ("Basis", "bind"), _), _), _), t1), _), t2), _), - (EFfi ("Basis", "transaction_monad"), _)), _), - trans1), _), trans2), _)), _), - trans3) => - let - val e'' = (EFfi ("Basis", "bind"), loc) - val e'' = (ECApp (e'', (CFfi ("Basis", "transaction"), loc)), loc) - val e'' = (ECApp (e'', t2), loc) - val e'' = (ECApp (e'', t3), loc) - val e'' = (EApp (e'', (EFfi ("Basis", "transaction_monad"), loc)), loc) - val e'' = (EApp (e'', (EApp (E.liftExpInExp 0 trans2, (ERel 0, loc)), loc)), loc) - val e'' = (EApp (e'', E.liftExpInExp 0 trans3), loc) - val e'' = (EAbs ("x", t1, (CApp ((CFfi ("Basis", "transaction"), loc), t3), loc), e''), loc) - - val e' = (EFfi ("Basis", "bind"), loc) - val e' = (ECApp (e', (CFfi ("Basis", "transaction"), loc)), loc) - val e' = (ECApp (e', t1), loc) - val e' = (ECApp (e', t3), loc) - val e' = (EApp (e', (EFfi ("Basis", "transaction_monad"), loc)), loc) - val e' = (EApp (e', trans1), loc) - val e' = (EApp (e', e''), loc) - val (e', st) = doExp (e', st) - in - (#1 e', st) - end - - | EApp ( - (EApp - ((EApp ((ECApp ((ECApp ((ECApp ((EFfi ("Basis", "bind"), _), _), _), _), _), _), _), - (EFfi ("Basis", "transaction_monad"), _)), _), - _), loc), - (EAbs (_, _, _, (EWrite _, _)), _)) => (e, st) - - | EApp ( - (EApp - ((EApp ((ECApp ((ECApp ((ECApp ((EFfi ("Basis", "bind"), _), _), _), t1), _), t2), _), - (EFfi ("Basis", "transaction_monad"), _)), _), - trans1), loc), - trans2) => - (case (serverSide (#cpsed_range st) trans1, clientSide (#cpsed_range st) trans1, - serverSide (#cpsed_range st) trans2, clientSide (#cpsed_range st) trans2) of - (true, false, _, true) => newRpc (trans1, trans2, st) - | (_, true, true, false) => - (case #1 trans2 of - EAbs (x, dom, ran, trans2) => - let - val (trans2, st) = newRpc (trans2, dummyK loc, st) - val trans2 = (EAbs (x, dom, ran, (trans2, loc)), loc) - - val e = (EFfi ("Basis", "bind"), loc) - val e = (ECApp (e, (CFfi ("Basis", "transaction"), loc)), loc) - val e = (ECApp (e, t1), loc) - val e = (ECApp (e, t2), loc) - val e = (EApp (e, (EFfi ("Basis", "transaction_monad"), loc)), loc) - val e = (EApp (e, trans1), loc) - val e = EApp (e, trans2) - in - (e, st) - end - | _ => (e, st)) - | (true, true, _, _) => newCps (t1, t2, trans1, trans2, st) - - | _ => (e, st)) - - | ERecord xes => - let - val loc = case xes of - [] => ErrorMsg.dummySpan - | (_, (_, loc), _) :: _ => loc - - fun candidate (x, e) = - String.isPrefix "On" x - andalso serverSide (#cpsed_range st) e - andalso not (clientSide (#cpsed_range st) e) - in - if List.exists (fn ((CName x, _), e, _) => candidate (x, e) - | _ => false) xes then - let - val (xes, st) = ListUtil.foldlMap - (fn (y as (nm as (CName x, _), e, t), st) => - if candidate (x, e) then - let - val (e, st) = newRpc (e, dummyK loc, st) - in - ((nm, (e, loc), t), st) - end - else - (y, st) - | y => y) - st xes - in - (ERecord xes, st) - end - else - (e, st) - end + EApp ((ECApp ((EFfi ("Basis", "rpc"), _), ran), _), trans) => newRpc (trans, st) + | EApp ((ECApp ((ENamed n, _), ran), _), trans) => + if IS.member (rpcBaseIds, n) then + newRpc (trans, st) + else + (e, st) | _ => (e, st) end @@ -456,32 +149,14 @@ decl = fn x => x} st d in - (List.revAppend (case #cps_decls st of - [] => [d] - | ds => - case d of - (DValRec vis, loc) => [(DValRec (ds @ vis), loc)] - | (_, loc) => [d, (DValRec ds, loc)], - #export_decls st), - {cpsed = #cpsed st, - cpsed_range = #cpsed_range st, - cps_decls = [], - - exported = #exported st, - export_decls = [], - - maxName = #maxName st}) + (#export_decls st @ [d], + {exported = #exported st, + export_decls = []}) end val (file, _) = ListUtil.foldlMapConcat decl - {cpsed = IM.empty, - cpsed_range = IM.empty, - cps_decls = [], - - exported = IS.empty, - export_decls = [], - - maxName = U.File.maxName file + 1} + {exported = IS.empty, + export_decls = []} file in file