Mercurial > urweb
changeset 177:5d030ee143e2
Case through corify
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sat, 02 Aug 2008 11:15:32 -0400 |
parents | 33d4a8eea484 |
children | eb3f9913bf31 |
files | src/core.sml src/core_env.sig src/core_env.sml src/core_print.sml src/core_util.sml src/corify.sml src/monoize.sml tests/caseMod.lac |
diffstat | 8 files changed, 247 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/src/core.sml Thu Jul 31 16:28:55 2008 -0400 +++ b/src/core.sml Sat Aug 02 11:15:32 2008 -0400 @@ -59,10 +59,24 @@ withtype con = con' located +datatype patCon = + PConVar of int + | PConFfi of string * string + +datatype pat' = + PWild + | PVar of string + | PPrim of Prim.t + | PCon of patCon * pat option + | PRecord of (string * pat) list + +withtype pat = pat' located + datatype exp' = EPrim of Prim.t | ERel of int | ENamed of int + | ECon of int * exp option | EFfi of string * string | EFfiApp of string * string * exp list | EApp of exp * exp @@ -75,6 +89,8 @@ | ECut of exp * con * { field : con, rest : con } | EFold of kind + | ECase of exp * (pat * exp) list * con + | EWrite of exp | EClosure of int * exp list
--- a/src/core_env.sig Thu Jul 31 16:28:55 2008 -0400 +++ b/src/core_env.sig Sat Aug 02 11:15:32 2008 -0400 @@ -45,6 +45,8 @@ val pushDatatype : env -> string -> int -> (string * int * Core.con option) list -> env val lookupDatatype : env -> int -> string * (string * int * Core.con option) list + val lookupConstructor : env -> int -> string * Core.con option * int + val pushERel : env -> string -> Core.con -> env val lookupERel : env -> int -> string * Core.con
--- a/src/core_env.sml Thu Jul 31 16:28:55 2008 -0400 +++ b/src/core_env.sml Sat Aug 02 11:15:32 2008 -0400 @@ -62,6 +62,7 @@ namedC : (string * kind * con option) IM.map, datatypes : (string * (string * int * con option) list) IM.map, + constructors : (string * con option * int) IM.map, relE : (string * con) list, namedE : (string * con * exp option * string) IM.map @@ -72,6 +73,7 @@ namedC = IM.empty, datatypes = IM.empty, + constructors = IM.empty, relE = [], namedE = IM.empty @@ -82,6 +84,7 @@ namedC = IM.map (fn (x, k, co) => (x, k, Option.map lift co)) (#namedC env), datatypes = #datatypes env, + constructors = #constructors env, relE = map (fn (x, c) => (x, lift c)) (#relE env), namedE = IM.map (fn (x, c, eo, s) => (x, lift c, eo, s)) (#namedE env)} @@ -95,6 +98,7 @@ namedC = IM.insert (#namedC env, n, (x, k, co)), datatypes = #datatypes env, + constructors = #constructors env, relE = #relE env, namedE = #namedE env} @@ -109,6 +113,9 @@ namedC = #namedC env, datatypes = IM.insert (#datatypes env, n, (x, xncs)), + constructors = foldl (fn ((x, n, to), constructors) => + IM.insert (constructors, n, (x, to, n))) + (#constructors env) xncs, relE = #relE env, namedE = #namedE env} @@ -118,11 +125,17 @@ NONE => raise UnboundNamed n | SOME x => x +fun lookupConstructor (env : env) n = + case IM.find (#constructors env, n) of + NONE => raise UnboundNamed n + | SOME x => x + fun pushERel (env : env) x t = {relC = #relC env, namedC = #namedC env, datatypes = #datatypes env, + constructors = #constructors env, relE = (x, t) :: #relE env, namedE = #namedE env} @@ -136,6 +149,7 @@ namedC = #namedC env, datatypes = #datatypes env, + constructors = #constructors env, relE = #relE env, namedE = IM.insert (#namedE env, n, (x, t, eo, s))}
--- a/src/core_print.sml Thu Jul 31 16:28:55 2008 -0400 +++ b/src/core_print.sml Sat Aug 02 11:15:32 2008 -0400 @@ -152,6 +152,43 @@ string (#1 (E.lookupENamed env n))) handle E.UnboundNamed _ => string ("UNBOUNDN_" ^ Int.toString n) +fun p_con_named env n = + (if !debug then + string (#1 (E.lookupConstructor env n) ^ "__" ^ Int.toString n) + else + string (#1 (E.lookupConstructor env n))) + handle E.UnboundNamed _ => string ("CONSTRUCTOR_" ^ Int.toString n) + +fun p_patCon env pc = + case pc of + PConVar n => p_con_named env n + | PConFfi (m, x) => box [string "FFI(", + string m, + string ".", + string x, + string ")"] + +fun p_pat' par env (p, _) = + case p of + PWild => string "_" + | PVar s => string s + | PPrim p => Prim.p_t p + | PCon (n, NONE) => p_patCon env n + | PCon (n, SOME p) => parenIf par (box [p_patCon env n, + space, + p_pat' true env p]) + | PRecord xps => + box [string "{", + p_list_sep (box [string ",", space]) (fn (x, p) => + box [string x, + space, + string "=", + space, + p_pat env p]) xps, + string "}"] + +and p_pat x = p_pat' false x + fun p_exp' par env (e, _) = case e of EPrim p => Prim.p_t p @@ -162,6 +199,10 @@ string (#1 (E.lookupERel env n))) handle E.UnboundRel _ => string ("UNBOUND_" ^ Int.toString n)) | ENamed n => p_enamed env n + | ECon (n, NONE) => p_con_named env n + | ECon (n, SOME e) => parenIf par (box [p_con_named env n, + space, + p_exp' true env e]) | EFfi (m, x) => box [string "FFI(", string m, string ".", string x, string ")"] | EFfiApp (m, x, es) => box [string "FFI(", string m, @@ -249,6 +290,19 @@ p_con' true env c]) | EFold _ => string "fold" + | ECase (e, pes, _) => parenIf par (box [string "case", + space, + p_exp env e, + space, + string "of", + space, + p_list_sep (box [space, string "|", space]) + (fn (p, e) => box [p_pat env p, + space, + string "=>", + space, + p_exp env e]) pes]) + | EWrite e => box [string "write(", p_exp env e, string ")"]
--- a/src/core_util.sml Thu Jul 31 16:28:55 2008 -0400 +++ b/src/core_util.sml Sat Aug 02 11:15:32 2008 -0400 @@ -227,6 +227,11 @@ EPrim _ => S.return2 eAll | ERel _ => S.return2 eAll | ENamed _ => S.return2 eAll + | ECon (_, NONE) => S.return2 eAll + | ECon (n, SOME e) => + S.map2 (mfe ctx e, + fn e' => + (ECon (n, SOME e'), loc)) | EFfi _ => S.return2 eAll | EFfiApp (m, x, es) => S.map2 (ListUtil.mapfold (fn e => mfe ctx e) es, @@ -297,6 +302,17 @@ fn k' => (EFold k', loc)) + | ECase (e, pes, t) => + S.bind2 (mfe ctx e, + fn e' => + S.bind2 (ListUtil.mapfold (fn (p, e) => + S.map2 (mfe ctx e, + fn e' => (p, e'))) pes, + fn pes' => + S.map2 (mfc ctx t, + fn t' => + (ECase (e', pes', t'), loc)))) + | EWrite e => S.map2 (mfe ctx e, fn e' =>
--- a/src/corify.sml Thu Jul 31 16:28:55 2008 -0400 +++ b/src/corify.sml Sat Aug 02 11:15:32 2008 -0400 @@ -71,11 +71,15 @@ val lookupConById : t -> int -> int option val lookupConByName : t -> string -> core_con + val bindConstructor : t -> string -> int -> L'.patCon -> t + val lookupConstructorByName : t -> string -> L'.patCon + val lookupConstructorById : t -> int -> L'.patCon + datatype core_val = ENormal of int | EFfi of string * L'.con val bindVal : t -> string -> int -> t * int - val bindConstructor : t -> string -> int -> t + val bindConstructorVal : t -> string -> int -> t val lookupValById : t -> int -> int option val lookupValByName : t -> string -> core_val @@ -90,6 +94,7 @@ datatype flattening = FNormal of {cons : int SM.map, + constructors : L'.patCon SM.map, vals : int SM.map, strs : flattening SM.map, funs : (string * int * L.str) SM.map} @@ -98,6 +103,7 @@ type t = { cons : int IM.map, + constructors : L'.patCon IM.map, vals : int IM.map, strs : flattening IM.map, funs : (string * int * L.str) IM.map, @@ -107,15 +113,17 @@ val empty = { cons = IM.empty, + constructors = IM.empty, vals = IM.empty, strs = IM.empty, funs = IM.empty, - current = FNormal { cons = SM.empty, vals = SM.empty, strs = SM.empty, funs = SM.empty }, + current = FNormal { cons = SM.empty, constructors = SM.empty, vals = SM.empty, strs = SM.empty, funs = SM.empty }, nested = [] } -fun debug ({current = FNormal {cons, vals, strs, funs}, ...} : t) = +fun debug ({current = FNormal {cons, constructors, vals, strs, funs}, ...} : t) = print ("cons: " ^ Int.toString (SM.numItems cons) ^ "; " + ^ "constructors: " ^ Int.toString (SM.numItems constructors) ^ "; " ^ "vals: " ^ Int.toString (SM.numItems vals) ^ "; " ^ "strs: " ^ Int.toString (SM.numItems strs) ^ "; " ^ "funs: " ^ Int.toString (SM.numItems funs) ^ "\n") @@ -129,20 +137,22 @@ ENormal of int | EFfi of string * L'.con -fun bindCon {cons, vals, strs, funs, current, nested} s n = +fun bindCon {cons, constructors, vals, strs, funs, current, nested} s n = let val n' = alloc () val current = case current of FFfi _ => raise Fail "Binding inside FFfi" - | FNormal {cons, vals, strs, funs} => + | FNormal {cons, constructors, vals, strs, funs} => FNormal {cons = SM.insert (cons, s, n'), + constructors = constructors, vals = vals, strs = strs, funs = funs} in ({cons = IM.insert (cons, n, n'), + constructors = constructors, vals = vals, strs = strs, funs = funs, @@ -161,20 +171,22 @@ NONE => raise Fail "Corify.St.lookupConByName" | SOME n => CNormal n -fun bindVal {cons, vals, strs, funs, current, nested} s n = +fun bindVal {cons, constructors, vals, strs, funs, current, nested} s n = let val n' = alloc () val current = case current of FFfi _ => raise Fail "Binding inside FFfi" - | FNormal {cons, vals, strs, funs} => + | FNormal {cons, constructors, vals, strs, funs} => FNormal {cons = cons, + constructors = constructors, vals = SM.insert (vals, s, n'), strs = strs, funs = funs} in ({cons = cons, + constructors = constructors, vals = IM.insert (vals, n, n'), strs = strs, funs = funs, @@ -183,18 +195,20 @@ n') end -fun bindConstructor {cons, vals, strs, funs, current, nested} s n = +fun bindConstructorVal {cons, constructors, vals, strs, funs, current, nested} s n = let val current = case current of FFfi _ => raise Fail "Binding inside FFfi" - | FNormal {cons, vals, strs, funs} => + | FNormal {cons, constructors, vals, strs, funs} => FNormal {cons = cons, + constructors = constructors, vals = SM.insert (vals, s, n), strs = strs, funs = funs} in {cons = cons, + constructors = constructors, vals = IM.insert (vals, n, n), strs = strs, funs = funs, @@ -202,6 +216,7 @@ nested = nested} end + fun lookupValById ({vals, ...} : t) n = IM.find (vals, n) fun lookupValByName ({current, ...} : t) x = @@ -215,26 +230,64 @@ NONE => raise Fail "Corify.St.lookupValByName" | SOME n => ENormal n -fun enter {cons, vals, strs, funs, current, nested} = +fun bindConstructor {cons, constructors, vals, strs, funs, current, nested} s n n' = + let + val current = + case current of + FFfi _ => raise Fail "Binding inside FFfi" + | FNormal {cons, constructors, vals, strs, funs} => + FNormal {cons = cons, + constructors = SM.insert (constructors, s, n'), + vals = vals, + strs = strs, + funs = funs} + in + {cons = cons, + constructors = IM.insert (constructors, n, n'), + vals = vals, + strs = strs, + funs = funs, + current = current, + nested = nested} + end + +fun lookupConstructorById ({constructors, ...} : t) n = + case IM.find (constructors, n) of + NONE => raise Fail "Corify.St.lookupConstructorById" + | SOME x => x + +fun lookupConstructorByName ({current, ...} : t) x = + case current of + FFfi {mod = m, ...} => L'.PConFfi (m, x) + | FNormal {constructors, ...} => + case SM.find (constructors, x) of + NONE => raise Fail "Corify.St.lookupConstructorByName" + | SOME n => n + +fun enter {cons, constructors, vals, strs, funs, current, nested} = {cons = cons, + constructors = constructors, vals = vals, strs = strs, funs = funs, current = FNormal {cons = SM.empty, + constructors = SM.empty, vals = SM.empty, strs = SM.empty, funs = SM.empty}, nested = current :: nested} fun dummy f = {cons = IM.empty, + constructors = IM.empty, vals = IM.empty, strs = IM.empty, funs = IM.empty, current = f, nested = []} -fun leave {cons, vals, strs, funs, current, nested = m1 :: rest} = +fun leave {cons, constructors, vals, strs, funs, current, nested = m1 :: rest} = {outer = {cons = cons, + constructors = constructors, vals = vals, strs = strs, funs = funs, @@ -245,14 +298,17 @@ fun ffi m vals = dummy (FFfi {mod = m, vals = vals}) -fun bindStr ({cons, vals, strs, funs, - current = FNormal {cons = mcons, vals = mvals, strs = mstrs, funs = mfuns}, nested} : t) +fun bindStr ({cons, constructors, vals, strs, funs, + current = FNormal {cons = mcons, constructors = mconstructors, + vals = mvals, strs = mstrs, funs = mfuns}, nested} : t) x n ({current = f, ...} : t) = {cons = cons, + constructors = constructors, vals = vals, strs = IM.insert (strs, n, f), funs = funs, current = FNormal {cons = mcons, + constructors = mconstructors, vals = mvals, strs = SM.insert (mstrs, x, f), funs = mfuns}, @@ -270,14 +326,17 @@ | SOME f => dummy f) | lookupStrByName _ = raise Fail "Corify.St.lookupStrByName" -fun bindFunctor ({cons, vals, strs, funs, - current = FNormal {cons = mcons, vals = mvals, strs = mstrs, funs = mfuns}, nested} : t) +fun bindFunctor ({cons, constructors, vals, strs, funs, + current = FNormal {cons = mcons, constructors = mconstructors, + vals = mvals, strs = mstrs, funs = mfuns}, nested} : t) x n xa na str = {cons = cons, + constructors = constructors, vals = vals, strs = strs, funs = IM.insert (funs, n, (xa, na, str)), current = FNormal {cons = mcons, + constructors = mconstructors, vals = mvals, strs = mstrs, funs = SM.insert (mfuns, x, (xa, na, str))}, @@ -338,6 +397,25 @@ | L.CFold (k1, k2) => (L'.CFold (corifyKind k1, corifyKind k2), loc) | L.CUnit => (L'.CUnit, loc) +fun corifyPatCon st pc = + case pc of + L.PConVar n => St.lookupConstructorById st n + | L.PConProj (m1, ms, x) => + let + val st = St.lookupStrById st m1 + val st = foldl St.lookupStrByName st ms + in + St.lookupConstructorByName st x + end + +fun corifyPat st (p, loc) = + case p of + L.PWild => (L'.PWild, loc) + | L.PVar x => (L'.PVar x, loc) + | L.PPrim p => (L'.PPrim p, loc) + | L.PCon (pc, po) => (L'.PCon (corifyPatCon st pc, Option.map (corifyPat st) po), loc) + | L.PRecord xps => (L'.PRecord (map (fn (x, p) => (x, corifyPat st p)) xps), loc) + fun corifyExp st (e, loc) = case e of L.EPrim p => (L'.EPrim p, loc) @@ -394,7 +472,12 @@ | L.ECut (e1, c, {field, rest}) => (L'.ECut (corifyExp st e1, corifyCon st c, {field = corifyCon st field, rest = corifyCon st rest}), loc) | L.EFold k => (L'.EFold (corifyKind k), loc) - | L.ECase _ => raise Fail "Corify ECase" + + | L.ECase (e, pes, t) => (L'.ECase (corifyExp st e, + map (fn (p, e) => (corifyPat st p, corifyExp st e)) pes, + corifyCon st t), + loc) + | L.EWrite e => (L'.EWrite (corifyExp st e), loc) fun corifyDecl ((d, loc : EM.span), st) = @@ -410,27 +493,47 @@ val (st, n) = St.bindCon st x n val (xncs, st) = ListUtil.foldlMap (fn ((x, n, co), st) => let - val st = St.bindConstructor st x n + val st = St.bindConstructor st x n (L'.PConVar n) + val st = St.bindConstructorVal st x n val co = Option.map (corifyCon st) co in ((x, n, co), st) end) st xncs + + val t = (L'.CNamed n, loc) + val dcons = map (fn (x, n, to) => + let + val (e, t) = + case to of + NONE => ((L'.ECon (n, NONE), loc), t) + | SOME t' => ((L'.EAbs ("x", t', t, + (L'.ECon (n, SOME (L'.ERel 0, loc)), loc)), + loc), + (L'.TFun (t', t), loc)) + in + (L'.DVal (x, n, t, e, ""), loc) + end) xncs in - ([(L'.DDatatype (x, n, xncs), loc)], st) + ((L'.DDatatype (x, n, xncs), loc) :: dcons, st) end | L.DDatatypeImp (x, n, m1, ms, s, xncs) => let val (st, n) = St.bindCon st x n val c = corifyCon st (L.CModProj (m1, ms, s), loc) + val m = foldl (fn (x, m) => (L.StrProj (m, x), loc)) (L.StrVar m1, loc) ms + val (_, {inner, ...}) = corifyStr (m, st) + val (xncs, st) = ListUtil.foldlMap (fn ((x, n, co), st) => let + val n' = St.lookupConstructorByName inner x + val st = St.bindConstructor st x n n' val (st, n) = St.bindVal st x n val co = Option.map (corifyCon st) co in ((x, n, co), st) end) st xncs - + val cds = map (fn (x, n, co) => let val t = case co of
--- a/src/monoize.sml Thu Jul 31 16:28:55 2008 -0400 +++ b/src/monoize.sml Sat Aug 02 11:15:32 2008 -0400 @@ -171,6 +171,7 @@ L.EPrim p => (L'.EPrim p, loc) | L.ERel n => (L'.ERel n, loc) | L.ENamed n => (L'.ENamed n, loc) + | L.ECon _ => raise Fail "Monoize ECon" | L.EFfi mx => (L'.EFfi mx, loc) | L.EFfiApp (m, x, es) => (L'.EFfiApp (m, x, map (monoExp (env, st)) es), loc) @@ -448,6 +449,9 @@ | L.EField (e, x, _) => (L'.EField (monoExp (env, st) e, monoName env x), loc) | L.ECut _ => poly () | L.EFold _ => poly () + + | L.ECase _ => raise Fail "Monoize ECase" + | L.EWrite e => (L'.EWrite (monoExp (env, st) e), loc) | L.EClosure (n, es) => (L'.EClosure (n, map (monoExp (env, st)) es), loc)
--- a/tests/caseMod.lac Thu Jul 31 16:28:55 2008 -0400 +++ b/tests/caseMod.lac Sat Aug 02 11:15:32 2008 -0400 @@ -9,11 +9,27 @@ val g = fn x : t => case x of M.A => B | B => M.A structure N = struct - datatype t = C of t | D + datatype u = C of t | D end -val h = fn x : N.t => case x of N.C x => x | N.D => M.A +val h = fn x : N.u => case x of N.C x => x | N.D => M.A -datatype u = datatype N.t +datatype u = datatype N.u val i = fn x : u => case x of N.C x => x | D => M.A + +val toString = fn x => + case x of + C A => "C A" + | C B => "C B" + | D => "D" + +val page = fn x => <html><body> + {cdata (toString x)} +</body></html> + +val main : unit -> page = fn () => <html><body> + <li> <a link={page (C A)}>C A</a></li> + <li> <a link={page (C B)}>C B</a></li> + <li> <a link={page D}>D</a></li> +</body></html>