Mercurial > urweb
changeset 26:4ab19c19665f
Closure conversion
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Tue, 10 Jun 2008 15:56:33 -0400 |
parents | 0a762c73824d |
children | 145b536fc702 |
files | src/cloconv.sig src/cloconv.sml src/compiler.sig src/compiler.sml src/core.sml src/core_print.sml src/core_util.sml src/corify.sml src/elab.sml src/elab_print.sml src/elab_util.sml src/elaborate.sml src/flat.sml src/flat_env.sig src/flat_env.sml src/flat_print.sig src/flat_print.sml src/flat_util.sig src/flat_util.sml src/list_util.sig src/list_util.sml src/mono.sml src/mono_print.sml src/mono_util.sig src/mono_util.sml src/monoize.sml src/reduce.sml src/sources tests/cloconv.lac tests/curry.lac tests/curry3.lac |
diffstat | 31 files changed, 1609 insertions(+), 55 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cloconv.sig Tue Jun 10 15:56:33 2008 -0400 @@ -0,0 +1,32 @@ +(* Copyright (c) 2008, Adam Chlipala + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - The names of contributors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *) + +signature CLOCONV = sig + + val cloconv : Mono.file -> Flat.file + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cloconv.sml Tue Jun 10 15:56:33 2008 -0400 @@ -0,0 +1,195 @@ +(* Copyright (c) 2008, Adam Chlipala + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - The names of contributors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *) + +structure Cloconv :> CLOCONV = struct + +structure L = Mono +structure L' = Flat + +structure IS = IntBinarySet + +structure U = FlatUtil +structure E = FlatEnv + +open Print.PD +open Print + +val liftExpInExp = + U.Exp.mapB {typ = fn t => t, + exp = fn bound => fn e => + case e of + L'.ERel xn => + if xn < bound then + e + else + L'.ERel (xn + 1) + | _ => e, + bind = fn (bound, U.Exp.RelE _) => bound + 1 + | (bound, _) => bound} +val subExpInExp = + U.Exp.mapB {typ = fn t => t, + exp = fn (xn, rep) => fn e => + case e of + L'.ERel xn' => + if xn = xn' then + #1 rep + else + e + | _ => e, + bind = fn ((xn, rep), U.Exp.RelE _) => (xn+1, liftExpInExp 0 rep) + | (ctx, _) => ctx} + + +fun ccTyp (t, loc) = + case t of + L.TFun (t1, t2) => (L'.TFun (ccTyp t1, ccTyp t2), loc) + | L.TRecord xts => (L'.TRecord (map (fn (x, t) => (x, ccTyp t)) xts), loc) + | L.TNamed n => (L'.TNamed n, loc) + +structure Ds :> sig + type t + + val empty : t + + val exp : t -> string * int * L'.typ * L'.exp -> t + val func : t -> string * L'.typ * L'.typ * L'.exp -> t * int + val decls : t -> L'.decl list + + val enter : t -> t + val used : t * int -> t + val leave : t -> t + val listUsed : t -> int list +end = struct + +type t = int * L'.decl list * IS.set + +val empty = (0, [], IS.empty) + +fun exp (fc, ds, vm) (v as (_, _, _, (_, loc))) = (fc, (L'.DVal v, loc) :: ds, vm) + +fun func (fc, ds, vm) (x, dom, ran, e as (_, loc)) = + ((fc+1, (L'.DFun (fc, x, dom, ran, e), loc) :: ds, vm), fc) + +fun decls (_, ds, _) = rev ds + +fun enter (fc, ds, vm) = (fc, ds, IS.map (fn n => n + 1) vm) +fun used ((fc, ds, vm), n) = (fc, ds, IS.add (vm, n)) +fun leave (fc, ds, vm) = (fc, ds, IS.map (fn n => n - 1) (IS.delete (vm, 0) handle NotFound => vm)) + +fun listUsed (_, _, vm) = IS.listItems vm + +end + + +fun ccExp env ((e, loc), D) = + case e of + L.EPrim p => ((L'.EPrim p, loc), D) + | L.ERel n => ((L'.ERel n, loc), Ds.used (D, n)) + | L.ENamed n => ((L'.ENamed n, loc), D) + | L.EApp (e1, e2) => + let + val (e1, D) = ccExp env (e1, D) + val (e2, D) = ccExp env (e2, D) + in + ((L'.ELet ([("closure", e1), + ("arg", liftExpInExp 0 e2), + ("code", (L'.EField ((L'.ERel 1, loc), "func"), loc)), + ("env", (L'.EField ((L'.ERel 2, loc), "env"), loc))], + (L'.EApp ((L'.ERel 1, loc), + (L'.ERecord [("env", (L'.ERel 0, loc)), + ("arg", (L'.ERel 2, loc))], loc)), loc)), loc), D) + end + | L.EAbs (x, dom, ran, e) => + let + val dom = ccTyp dom + val ran = ccTyp ran + val (e, D) = ccExp (E.pushERel env x dom) (e, Ds.enter D) + val ns = Ds.listUsed D + val ns = List.filter (fn n => n <> 0) ns + val D = Ds.leave D + + (*val () = Print.preface ("Before", FlatPrint.p_exp FlatEnv.basis e) + val () = List.app (fn (x, t) => preface ("Bound", box [string x, + space, + string ":", + space, + FlatPrint.p_typ env t])) + (E.listERels env) + val () = List.app (fn n => preface ("Free", FlatPrint.p_exp (E.pushERel env x dom) + (L'.ERel n, loc))) ns*) + val body = foldl (fn (n, e) => + subExpInExp (n, (L'.EField ((L'.ERel 1, loc), "fv" ^ Int.toString n), loc)) e) + e ns + (*val () = Print.preface (" After", FlatPrint.p_exp FlatEnv.basis body)*) + val body = (L'.ELet ([("env", (L'.EField ((L'.ERel 0, loc), "env"), loc)), + ("arg", (L'.EField ((L'.ERel 1, loc), "arg"), loc))], + body), loc) + + val envT = (L'.TRecord (map (fn n => ("fv" ^ Int.toString n, #2 (E.lookupERel env (n-1)))) ns), loc) + val (D, fi) = Ds.func D (x, (L'.TRecord [("env", envT), ("arg", dom)], loc), ran, body) + in + ((L'.ERecord [("code", (L'.ECode fi, loc)), + ("env", (L'.ERecord (map (fn n => ("fv" ^ Int.toString n, + (L'.ERel (n-1), loc))) ns), loc))], loc), D) + end + + | L.ERecord xes => + let + val (xes, D) = ListUtil.foldlMap (fn ((x, e), D) => + let + val (e, D) = ccExp env (e, D) + in + ((x, e), D) + end) D xes + in + ((L'.ERecord xes, loc), D) + end + | L.EField (e1, x) => + let + val (e1, D) = ccExp env (e1, D) + in + ((L'.EField (e1, x), loc), D) + end + +fun ccDecl ((d, loc), D) = + case d of + L.DVal (x, n, t, e) => + let + val t = ccTyp t + val (e, D) = ccExp E.basis (e, D) + in + Ds.exp D (x, n, t, e) + end + +fun cloconv ds = + let + val D = foldl ccDecl Ds.empty ds + in + Ds.decls D + end + +end
--- a/src/compiler.sig Tue Jun 10 13:14:45 2008 -0400 +++ b/src/compiler.sig Tue Jun 10 15:56:33 2008 -0400 @@ -35,6 +35,7 @@ val reduce : ElabEnv.env -> CoreEnv.env -> string -> Core.file option val shake : ElabEnv.env -> CoreEnv.env -> string -> Core.file option val monoize : ElabEnv.env -> CoreEnv.env -> string -> Mono.file option + val cloconv : ElabEnv.env -> CoreEnv.env -> string -> Flat.file option val testParse : string -> unit val testElaborate : string -> unit @@ -42,5 +43,6 @@ val testReduce : string -> unit val testShake : string -> unit val testMonoize : string -> unit + val testCloconv : string -> unit end
--- a/src/compiler.sml Tue Jun 10 13:14:45 2008 -0400 +++ b/src/compiler.sml Tue Jun 10 15:56:33 2008 -0400 @@ -103,6 +103,15 @@ else SOME (Monoize.monoize cenv file) +fun cloconv eenv cenv filename = + case monoize eenv cenv filename of + NONE => NONE + | SOME file => + if ErrorMsg.anyErrors () then + NONE + else + SOME (Cloconv.cloconv file) + fun testParse filename = case parse filename of NONE => print "Failed\n" @@ -155,4 +164,13 @@ handle MonoEnv.UnboundNamed n => print ("Unbound named " ^ Int.toString n ^ "\n") +fun testCloconv filename = + (case cloconv ElabEnv.basis CoreEnv.basis filename of + NONE => print "Failed\n" + | SOME file => + (Print.print (FlatPrint.p_file FlatEnv.basis file); + print "\n")) + handle FlatEnv.UnboundNamed n => + print ("Unbound named " ^ Int.toString n ^ "\n") + end
--- a/src/core.sml Tue Jun 10 13:14:45 2008 -0400 +++ b/src/core.sml Tue Jun 10 15:56:33 2008 -0400 @@ -59,7 +59,7 @@ | ERel of int | ENamed of int | EApp of exp * exp - | EAbs of string * con * exp + | EAbs of string * con * con * exp | ECApp of exp * con | ECAbs of string * kind * exp
--- a/src/core_print.sml Tue Jun 10 13:14:45 2008 -0400 +++ b/src/core_print.sml Tue Jun 10 15:56:33 2008 -0400 @@ -155,17 +155,17 @@ | EApp (e1, e2) => parenIf par (box [p_exp env e1, space, p_exp' true env e2]) - | EAbs (x, t, e) => parenIf par (box [string "fn", - space, - string x, - space, - string ":", - space, - p_con env t, - space, - string "=>", - space, - p_exp (E.pushERel env x t) e]) + | EAbs (x, t, _, e) => parenIf par (box [string "fn", + space, + string x, + space, + string ":", + space, + p_con env t, + space, + string "=>", + space, + p_exp (E.pushERel env x t) e]) | ECApp (e, c) => parenIf par (box [p_exp env e, space, string "[",
--- a/src/core_util.sml Tue Jun 10 13:14:45 2008 -0400 +++ b/src/core_util.sml Tue Jun 10 15:56:33 2008 -0400 @@ -222,12 +222,14 @@ S.map2 (mfe ctx e2, fn e2' => (EApp (e1', e2'), loc))) - | EAbs (x, t, e) => - S.bind2 (mfc ctx t, - fn t' => - S.map2 (mfe (bind (ctx, RelE (x, t))) e, - fn e' => - (EAbs (x, t', e'), loc))) + | EAbs (x, dom, ran, e) => + S.bind2 (mfc ctx dom, + fn dom' => + S.bind2 (mfc ctx ran, + fn ran' => + S.map2 (mfe (bind (ctx, RelE (x, dom'))) e, + fn e' => + (EAbs (x, dom', ran', e'), loc)))) | ECApp (e, c) => S.bind2 (mfe ctx e,
--- a/src/corify.sml Tue Jun 10 13:14:45 2008 -0400 +++ b/src/corify.sml Tue Jun 10 15:56:33 2008 -0400 @@ -68,7 +68,7 @@ | L.ERel n => (L'.ERel n, loc) | L.ENamed n => (L'.ENamed n, loc) | L.EApp (e1, e2) => (L'.EApp (corifyExp e1, corifyExp e2), loc) - | L.EAbs (x, t, e1) => (L'.EAbs (x, corifyCon t, corifyExp e1), loc) + | L.EAbs (x, dom, ran, e1) => (L'.EAbs (x, corifyCon dom, corifyCon ran, corifyExp e1), loc) | L.ECApp (e1, c) => (L'.ECApp (corifyExp e1, corifyCon c), loc) | L.ECAbs (_, x, k, e1) => (L'.ECAbs (x, corifyKind k, corifyExp e1), loc)
--- a/src/elab.sml Tue Jun 10 13:14:45 2008 -0400 +++ b/src/elab.sml Tue Jun 10 15:56:33 2008 -0400 @@ -69,7 +69,7 @@ | ERel of int | ENamed of int | EApp of exp * exp - | EAbs of string * con * exp + | EAbs of string * con * con * exp | ECApp of exp * con | ECAbs of explicitness * string * kind * exp
--- a/src/elab_print.sml Tue Jun 10 13:14:45 2008 -0400 +++ b/src/elab_print.sml Tue Jun 10 15:56:33 2008 -0400 @@ -170,17 +170,17 @@ | EApp (e1, e2) => parenIf par (box [p_exp env e1, space, p_exp' true env e2]) - | EAbs (x, t, e) => parenIf par (box [string "fn", - space, - string x, - space, - string ":", - space, - p_con env t, - space, - string "=>", - space, - p_exp (E.pushERel env x t) e]) + | EAbs (x, t, _, e) => parenIf par (box [string "fn", + space, + string x, + space, + string ":", + space, + p_con env t, + space, + string "=>", + space, + p_exp (E.pushERel env x t) e]) | ECApp (e, c) => parenIf par (box [p_exp env e, space, string "[",
--- a/src/elab_util.sml Tue Jun 10 13:14:45 2008 -0400 +++ b/src/elab_util.sml Tue Jun 10 15:56:33 2008 -0400 @@ -214,13 +214,15 @@ S.map2 (mfe ctx e2, fn e2' => (EApp (e1', e2'), loc))) - | EAbs (x, t, e) => - S.bind2 (mfc ctx t, - fn t' => - S.map2 (mfe (bind (ctx, RelE (x, t))) e, - fn e' => - (EAbs (x, t', e'), loc))) - + | EAbs (x, dom, ran, e) => + S.bind2 (mfc ctx dom, + fn dom' => + S.bind2 (mfc ctx ran, + fn ran' => + S.map2 (mfe (bind (ctx, RelE (x, dom'))) e, + fn e' => + (EAbs (x, dom', ran', e'), loc)))) + | ECApp (e, c) => S.bind2 (mfe ctx e, fn e' =>
--- a/src/elaborate.sml Tue Jun 10 13:14:45 2008 -0400 +++ b/src/elaborate.sml Tue Jun 10 15:56:33 2008 -0400 @@ -697,7 +697,7 @@ (case #1 (typeof env e1) of L'.TFun (_, c) => c | _ => raise Fail "typeof: Bad EApp") - | L'.EAbs (x, t, e1) => (L'.TFun (t, typeof (E.pushERel env x t) e1), loc) + | L'.EAbs (_, _, ran, _) => ran | L'.ECApp (e1, c) => (case #1 (typeof env e1) of L'.TCFun (_, _, _, c1) => subConInCon (0, c) c1 @@ -771,7 +771,7 @@ end val (e', et) = elabExp (E.pushERel env x t') e in - ((L'.EAbs (x, t', e'), loc), + ((L'.EAbs (x, t', et, e'), loc), (L'.TFun (t', et), loc)) end | L.ECApp (e, c) =>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/flat.sml Tue Jun 10 15:56:33 2008 -0400 @@ -0,0 +1,62 @@ +(* Copyright (c) 2008, Adam Chlipala + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - The names of contributors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *) + +structure Flat = struct + +type 'a located = 'a ErrorMsg.located + +datatype typ' = + TFun of typ * typ + | TCode of typ * typ + | TRecord of (string * typ) list + | TNamed of int + +withtype typ = typ' located + +datatype exp' = + EPrim of Prim.t + | ERel of int + | ENamed of int + | ECode of int + | EApp of exp * exp + + | ERecord of (string * exp) list + | EField of exp * string + + | ELet of (string * exp) list * exp + +withtype exp = exp' located + +datatype decl' = + DVal of string * int * typ * exp + | DFun of int * string * typ * typ * exp + +withtype decl = decl' located + +type file = decl list + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/flat_env.sig Tue Jun 10 15:56:33 2008 -0400 @@ -0,0 +1,54 @@ +(* Copyright (c) 2008, Adam Chlipala + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - The names of contributors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *) + +signature FLAT_ENV = sig + + type env + + val empty : env + val basis : env + + exception UnboundRel of int + exception UnboundNamed of int + exception UnboundF of int + + val pushTNamed : env -> string -> int -> Flat.typ option -> env + val lookupTNamed : env -> int -> string * Flat.typ option + + val pushERel : env -> string -> Flat.typ -> env + val lookupERel : env -> int -> string * Flat.typ + val listERels : env -> (string * Flat.typ) list + + val pushENamed : env -> string -> int -> Flat.typ -> env + val lookupENamed : env -> int -> string * Flat.typ + + val pushF : env -> int -> string -> Flat.typ -> Flat.typ -> env + val lookupF : env -> int -> string * Flat.typ * Flat.typ + + val declBinds : env -> Flat.decl -> env + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/flat_env.sml Tue Jun 10 15:56:33 2008 -0400 @@ -0,0 +1,126 @@ +(* Copyright (c) 2008, Adam Chlipala + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - The names of contributors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *) + +structure FlatEnv :> FLAT_ENV = struct + +open Flat + +structure IM = IntBinaryMap + + +exception UnboundRel of int +exception UnboundNamed of int +exception UnboundF of int + +type env = { + namedT : (string * typ option) IM.map, + + relE : (string * typ) list, + namedE : (string * typ) IM.map, + + F : (string * typ * typ) IM.map +} + +val empty = { + namedT = IM.empty, + + relE = [], + namedE = IM.empty, + + F = IM.empty +} + +fun pushTNamed (env : env) x n co = + {namedT = IM.insert (#namedT env, n, (x, co)), + + relE = #relE env, + namedE = #namedE env, + + F = #F env} + +fun lookupTNamed (env : env) n = + case IM.find (#namedT env, n) of + NONE => raise UnboundNamed n + | SOME x => x + +fun pushERel (env : env) x t = + {namedT = #namedT env, + + relE = (x, t) :: #relE env, + namedE = #namedE env, + + F = #F env} + +fun lookupERel (env : env) n = + (List.nth (#relE env, n)) + handle Subscript => raise UnboundRel n + +fun listERels (env : env) = #relE env + +fun pushENamed (env : env) x n t = + {namedT = #namedT env, + + relE = #relE env, + namedE = IM.insert (#namedE env, n, (x, t)), + + F = #F env} + +fun lookupENamed (env : env) n = + case IM.find (#namedE env, n) of + NONE => raise UnboundNamed n + | SOME x => x + +fun pushF (env : env) n x dom ran = + {namedT = #namedT env, + + relE = #relE env, + namedE = #namedE env, + + F = IM.insert (#F env, n, (x, dom, ran))} + +fun lookupF (env : env) n = + case IM.find (#F env, n) of + NONE => raise UnboundF n + | SOME x => x + +fun declBinds env (d, _) = + case d of + DVal (x, n, t, _) => pushENamed env x n t + | DFun (n, x, dom, ran, _) => pushF env n x dom ran + +fun bbind env x = + case ElabEnv.lookupC ElabEnv.basis x of + ElabEnv.NotBound => raise Fail "FlatEnv.bbind: Not bound" + | ElabEnv.Rel _ => raise Fail "FlatEnv.bbind: Rel" + | ElabEnv.Named (n, _) => pushTNamed env x n NONE + +val basis = empty +val basis = bbind basis "int" +val basis = bbind basis "float" +val basis = bbind basis "string" + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/flat_print.sig Tue Jun 10 15:56:33 2008 -0400 @@ -0,0 +1,38 @@ +(* Copyright (c) 2008, Adam Chlipala + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - The names of contributors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *) + +(* Pretty-printing Laconic/Web flat-code language *) + +signature FLAT_PRINT = sig + val p_typ : FlatEnv.env -> Flat.typ Print.printer + val p_exp : FlatEnv.env -> Flat.exp Print.printer + val p_decl : FlatEnv.env -> Flat.decl Print.printer + val p_file : FlatEnv.env -> Flat.file Print.printer + + val debug : bool ref +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/flat_print.sml Tue Jun 10 15:56:33 2008 -0400 @@ -0,0 +1,197 @@ +(* Copyright (c) 2008, Adam Chlipala + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - The names of contributors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *) + +(* Pretty-printing flat-code Laconic/Web *) + +structure FlatPrint :> FLAT_PRINT = struct + +open Print.PD +open Print + +open Flat + +structure E = FlatEnv + +val debug = ref false + +val dummyTyp = (TNamed 0, ErrorMsg.dummySpan) + +fun p_typ' par env (t, _) = + case t of + TFun (t1, t2) => parenIf par (box [p_typ' true env t1, + space, + string "->", + space, + p_typ env t2]) + | TCode (t1, t2) => parenIf par (box [p_typ' true env t1, + space, + string "-->", + space, + p_typ env t2]) + | TRecord xcs => box [string "{", + p_list (fn (x, t) => + box [string x, + space, + string ":", + space, + p_typ env t]) xcs, + string "}"] + | TNamed n => + if !debug then + string (#1 (E.lookupTNamed env n) ^ "__" ^ Int.toString n) + else + string (#1 (E.lookupTNamed env n)) + +and p_typ env = p_typ' false env + +fun p_exp' par env (e, _) = + case e of + EPrim p => Prim.p_t p + | ERel n => + ((if !debug then + string (#1 (E.lookupERel env n) ^ "_" ^ Int.toString n) + else + string (#1 (E.lookupERel env n))) + handle E.UnboundRel _ => string ("UNBOUND" ^ Int.toString n)) + | ENamed n => + if !debug then + string (#1 (E.lookupENamed env n) ^ "__" ^ Int.toString n) + else + string (#1 (E.lookupENamed env n)) + | ECode n => string ("code$" ^ Int.toString n) + | EApp (e1, e2) => parenIf par (box [p_exp env e1, + space, + p_exp' true env e2]) + + | ERecord xes => box [string "{", + p_list (fn (x, e) => + box [string x, + space, + string "=", + space, + p_exp env e]) xes, + string "}"] + | EField (e, x) => + box [p_exp' true env e, + string ".", + string x] + + | ELet (xes, e) => + let + val (env, pps) = foldl (fn ((x, e), (env, pps)) => + (E.pushERel env x dummyTyp, + List.revAppend ([space, + string "val", + space, + string x, + space, + string "=", + space, + p_exp env e], + pps))) + (env, []) xes + in + box [string "let", + space, + box (rev pps), + space, + string "in", + space, + p_exp env e, + space, + string "end"] + end + +and p_exp env = p_exp' false env + +fun p_decl env ((d, _) : decl) = + case d of + DVal (x, n, t, e) => + let + val xp = if !debug then + box [string x, + string "__", + string (Int.toString n)] + else + string x + in + box [string "val", + space, + xp, + space, + string ":", + space, + p_typ env t, + space, + string "=", + space, + p_exp env e] + + end + | DFun (n, x, dom, ran, e) => + let + val xp = if !debug then + box [string x, + string "__", + string (Int.toString n)] + else + string x + in + box [string "fun", + space, + string "code$", + string (Int.toString n), + space, + string "(", + xp, + space, + string ":", + space, + p_typ env dom, + string ")", + space, + string ":", + space, + p_typ env ran, + space, + string "=", + space, + p_exp (E.pushERel env x dom) e] + + end + +fun p_file env file = + let + val (_, pds) = ListUtil.mapfoldl (fn (d, env) => + (E.declBinds env d, + p_decl env d)) + env file + in + p_list_sep newline (fn x => x) pds + end + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/flat_util.sig Tue Jun 10 15:56:33 2008 -0400 @@ -0,0 +1,122 @@ +(* Copyright (c) 2008, Adam Chlipala + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - The names of contributors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *) + +signature FLAT_UTIL = sig + +structure Typ : sig + val mapfold : (Flat.typ', 'state, 'abort) Search.mapfolder + -> (Flat.typ, 'state, 'abort) Search.mapfolder + + val map : (Flat.typ' -> Flat.typ') + -> Flat.typ -> Flat.typ + + val fold : (Flat.typ' * 'state -> 'state) + -> 'state -> Flat.typ -> 'state + + val exists : (Flat.typ' -> bool) -> Flat.typ -> bool +end + +structure Exp : sig + datatype binder = + NamedT of string * int * Flat.typ option + | RelE of string * Flat.typ + | NamedE of string * int * Flat.typ * Flat.exp option + + val mapfoldB : {typ : (Flat.typ', 'state, 'abort) Search.mapfolder, + exp : ('typtext, Flat.exp', 'state, 'abort) Search.mapfolderB, + bind : 'typtext * binder -> 'typtext} + -> ('typtext, Flat.exp, 'state, 'abort) Search.mapfolderB + val mapfold : {typ : (Flat.typ', 'state, 'abort) Search.mapfolder, + exp : (Flat.exp', 'state, 'abort) Search.mapfolder} + -> (Flat.exp, 'state, 'abort) Search.mapfolder + + val map : {typ : Flat.typ' -> Flat.typ', + exp : Flat.exp' -> Flat.exp'} + -> Flat.exp -> Flat.exp + val mapB : {typ : Flat.typ' -> Flat.typ', + exp : 'typtext -> Flat.exp' -> Flat.exp', + bind : 'typtext * binder -> 'typtext} + -> 'typtext -> (Flat.exp -> Flat.exp) + + val fold : {typ : Flat.typ' * 'state -> 'state, + exp : Flat.exp' * 'state -> 'state} + -> 'state -> Flat.exp -> 'state + + val exists : {typ : Flat.typ' -> bool, + exp : Flat.exp' -> bool} -> Flat.exp -> bool +end + +structure Decl : sig + datatype binder = datatype Exp.binder + + val mapfoldB : {typ : (Flat.typ', 'state, 'abort) Search.mapfolder, + exp : ('typtext, Flat.exp', 'state, 'abort) Search.mapfolderB, + decl : ('typtext, Flat.decl', 'state, 'abort) Search.mapfolderB, + bind : 'typtext * binder -> 'typtext} + -> ('typtext, Flat.decl, 'state, 'abort) Search.mapfolderB + val mapfold : {typ : (Flat.typ', 'state, 'abort) Search.mapfolder, + exp : (Flat.exp', 'state, 'abort) Search.mapfolder, + decl : (Flat.decl', 'state, 'abort) Search.mapfolder} + -> (Flat.decl, 'state, 'abort) Search.mapfolder + + val fold : {typ : Flat.typ' * 'state -> 'state, + exp : Flat.exp' * 'state -> 'state, + decl : Flat.decl' * 'state -> 'state} + -> 'state -> Flat.decl -> 'state +end + +structure File : sig + datatype binder = + NamedT of string * int * Flat.typ option + | RelE of string * Flat.typ + | NamedE of string * int * Flat.typ * Flat.exp option + | F of int * string * Flat.typ * Flat.typ * Flat.exp + + val mapfoldB : {typ : (Flat.typ', 'state, 'abort) Search.mapfolder, + exp : ('typtext, Flat.exp', 'state, 'abort) Search.mapfolderB, + decl : ('typtext, Flat.decl', 'state, 'abort) Search.mapfolderB, + bind : 'typtext * binder -> 'typtext} + -> ('typtext, Flat.file, 'state, 'abort) Search.mapfolderB + + val mapfold : {typ : (Flat.typ', 'state, 'abort) Search.mapfolder, + exp : (Flat.exp', 'state, 'abort) Search.mapfolder, + decl : (Flat.decl', 'state, 'abort) Search.mapfolder} + -> (Flat.file, 'state, 'abort) Search.mapfolder + + val mapB : {typ : Flat.typ' -> Flat.typ', + exp : 'typtext -> Flat.exp' -> Flat.exp', + decl : 'typtext -> Flat.decl' -> Flat.decl', + bind : 'typtext * binder -> 'typtext} + -> 'typtext -> Flat.file -> Flat.file + + val fold : {typ : Flat.typ' * 'state -> 'state, + exp : Flat.exp' * 'state -> 'state, + decl : Flat.decl' * 'state -> 'state} + -> 'state -> Flat.file -> 'state +end + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/flat_util.sml Tue Jun 10 15:56:33 2008 -0400 @@ -0,0 +1,286 @@ +(* Copyright (c) 2008, Adam Chlipala + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - The names of contributors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *) + +structure FlatUtil :> FLAT_UTIL = struct + +open Flat + +structure S = Search + +structure Typ = struct + +fun mapfold fc = + let + fun mft c acc = + S.bindP (mft' c acc, fc) + + and mft' (cAll as (c, loc)) = + case c of + TFun (t1, t2) => + S.bind2 (mft t1, + fn t1' => + S.map2 (mft t2, + fn t2' => + (TFun (t1', t2'), loc))) + | TCode (t1, t2) => + S.bind2 (mft t1, + fn t1' => + S.map2 (mft t2, + fn t2' => + (TCode (t1', t2'), loc))) + | TRecord xts => + S.map2 (ListUtil.mapfold (fn (x, t) => + S.map2 (mft t, + fn t' => + (x, t'))) + xts, + fn xts' => (TRecord xts', loc)) + | TNamed _ => S.return2 cAll + in + mft + end + +fun map typ c = + case mapfold (fn c => fn () => S.Continue (typ c, ())) c () of + S.Return () => raise Fail "Flat_util.Typ.map" + | S.Continue (c, ()) => c + +fun fold typ s c = + case mapfold (fn c => fn s => S.Continue (c, typ (c, s))) c s of + S.Continue (_, s) => s + | S.Return _ => raise Fail "FlatUtil.Typ.fold: Impossible" + +fun exists typ k = + case mapfold (fn c => fn () => + if typ c then + S.Return () + else + S.Continue (c, ())) k () of + S.Return _ => true + | S.Continue _ => false + +end + +structure Exp = struct + +datatype binder = + NamedT of string * int * typ option + | RelE of string * typ + | NamedE of string * int * typ * exp option + +fun mapfoldB {typ = fc, exp = fe, bind} = + let + val mft = Typ.mapfold fc + + fun mfe ctx e acc = + S.bindP (mfe' ctx e acc, fe ctx) + + and mfe' ctx (eAll as (e, loc)) = + case e of + EPrim _ => S.return2 eAll + | ERel _ => S.return2 eAll + | ENamed _ => S.return2 eAll + | ECode _ => S.return2 eAll + | EApp (e1, e2) => + S.bind2 (mfe ctx e1, + fn e1' => + S.map2 (mfe ctx e2, + fn e2' => + (EApp (e1', e2'), loc))) + + | ERecord xes => + S.map2 (ListUtil.mapfold (fn (x, e) => + S.map2 (mfe ctx e, + fn e' => + (x, e'))) + xes, + fn xes' => + (ERecord xes', loc)) + | EField (e, x) => + S.map2 (mfe ctx e, + fn e' => + (EField (e', x), loc)) + + | ELet (xes, e) => + S.bind2 (ListUtil.mapfold (fn (x, e) => + S.map2 (mfe ctx e, + fn e' => + (x, e'))) + xes, + fn xes' => + S.map2 (mfe ctx e, + fn e' => + (ELet (xes', e'), loc))) + in + mfe + end + +fun mapfold {typ = fc, exp = fe} = + mapfoldB {typ = fc, + exp = fn () => fe, + bind = fn ((), _) => ()} () + +fun mapB {typ, exp, bind} ctx e = + case mapfoldB {typ = fn c => fn () => S.Continue (typ c, ()), + exp = fn ctx => fn e => fn () => S.Continue (exp ctx e, ()), + bind = bind} ctx e () of + S.Continue (e, ()) => e + | S.Return _ => raise Fail "FlatUtil.Exp.mapB: Impossible" + +fun map {typ, exp} e = + case mapfold {typ = fn c => fn () => S.Continue (typ c, ()), + exp = fn e => fn () => S.Continue (exp e, ())} e () of + S.Return () => raise Fail "Flat_util.Exp.map" + | S.Continue (e, ()) => e + +fun fold {typ, exp} s e = + case mapfold {typ = fn c => fn s => S.Continue (c, typ (c, s)), + exp = fn e => fn s => S.Continue (e, exp (e, s))} e s of + S.Continue (_, s) => s + | S.Return _ => raise Fail "FlatUtil.Exp.fold: Impossible" + +fun exists {typ, exp} k = + case mapfold {typ = fn c => fn () => + if typ c then + S.Return () + else + S.Continue (c, ()), + exp = fn e => fn () => + if exp e then + S.Return () + else + S.Continue (e, ())} k () of + S.Return _ => true + | S.Continue _ => false + +end + +structure Decl = struct + +datatype binder = datatype Exp.binder + +fun mapfoldB {typ = fc, exp = fe, decl = fd, bind} = + let + val mft = Typ.mapfold fc + + val mfe = Exp.mapfoldB {typ = fc, exp = fe, bind = bind} + + fun mfd ctx d acc = + S.bindP (mfd' ctx d acc, fd ctx) + + and mfd' ctx (dAll as (d, loc)) = + case d of + DVal (x, n, t, e) => + S.bind2 (mft t, + fn t' => + S.map2 (mfe ctx e, + fn e' => + (DVal (x, n, t', e'), loc))) + | DFun (n, x, dom, ran, e) => + S.bind2 (mft dom, + fn dom' => + S.bind2 (mft ran, + fn ran' => + S.map2 (mfe ctx e, + fn e' => + (DFun (n, x, dom', ran', e'), loc)))) + in + mfd + end + +fun mapfold {typ = fc, exp = fe, decl = fd} = + mapfoldB {typ = fc, + exp = fn () => fe, + decl = fn () => fd, + bind = fn ((), _) => ()} () + +fun fold {typ, exp, decl} s d = + case mapfold {typ = fn c => fn s => S.Continue (c, typ (c, s)), + exp = fn e => fn s => S.Continue (e, exp (e, s)), + decl = fn d => fn s => S.Continue (d, decl (d, s))} d s of + S.Continue (_, s) => s + | S.Return _ => raise Fail "FlatUtil.Decl.fold: Impossible" + +end + +structure File = struct + +datatype binder = + NamedT of string * int * typ option + | RelE of string * typ + | NamedE of string * int * typ * exp option + | F of int * string * Flat.typ * Flat.typ * Flat.exp + +fun mapfoldB (all as {bind, ...}) = + let + val mfd = Decl.mapfoldB all + + fun mff ctx ds = + case ds of + nil => S.return2 nil + | d :: ds' => + S.bind2 (mfd ctx d, + fn d' => + let + val b = + case #1 d' of + DVal (x, n, t, e) => NamedE (x, n, t, SOME e) + | DFun v => F v + val ctx' = bind (ctx, b) + in + S.map2 (mff ctx' ds', + fn ds' => + d' :: ds') + end) + in + mff + end + +fun mapfold {typ = fc, exp = fe, decl = fd} = + mapfoldB {typ = fc, + exp = fn () => fe, + decl = fn () => fd, + bind = fn ((), _) => ()} () + +fun mapB {typ, exp, decl, bind} ctx ds = + case mapfoldB {typ = fn c => fn () => S.Continue (typ c, ()), + exp = fn ctx => fn e => fn () => S.Continue (exp ctx e, ()), + decl = fn ctx => fn d => fn () => S.Continue (decl ctx d, ()), + bind = bind} ctx ds () of + S.Continue (ds, ()) => ds + | S.Return _ => raise Fail "FlatUtil.File.mapB: Impossible" + +fun fold {typ, exp, decl} s d = + case mapfold {typ = fn c => fn s => S.Continue (c, typ (c, s)), + exp = fn e => fn s => S.Continue (e, exp (e, s)), + decl = fn d => fn s => S.Continue (d, decl (d, s))} d s of + S.Continue (_, s) => s + | S.Return _ => raise Fail "FlatUtil.File.fold: Impossible" + +end + +end
--- a/src/list_util.sig Tue Jun 10 13:14:45 2008 -0400 +++ b/src/list_util.sig Tue Jun 10 15:56:33 2008 -0400 @@ -33,6 +33,8 @@ val mapfold : ('data, 'state, 'abort) Search.mapfolder -> ('data list, 'state, 'abort) Search.mapfolder + val foldlMap : ('data1 * 'state -> 'data2 * 'state) -> 'state -> 'data1 list -> 'data2 list * 'state + val search : ('a -> 'b option) -> 'a list -> 'b option end
--- a/src/list_util.sml Tue Jun 10 13:14:45 2008 -0400 +++ b/src/list_util.sml Tue Jun 10 15:56:33 2008 -0400 @@ -60,6 +60,21 @@ mf end +fun foldlMap f s = + let + fun fm (ls', s) ls = + case ls of + nil => (rev ls', s) + | h :: t => + let + val (h', s') = f (h, s) + in + fm (h' :: ls', s') t + end + in + fm ([], s) + end + fun search f = let fun s ls =
--- a/src/mono.sml Tue Jun 10 13:14:45 2008 -0400 +++ b/src/mono.sml Tue Jun 10 15:56:33 2008 -0400 @@ -41,7 +41,7 @@ | ERel of int | ENamed of int | EApp of exp * exp - | EAbs of string * typ * exp + | EAbs of string * typ * typ * exp | ERecord of (string * exp) list | EField of exp * string
--- a/src/mono_print.sml Tue Jun 10 13:14:45 2008 -0400 +++ b/src/mono_print.sml Tue Jun 10 15:56:33 2008 -0400 @@ -77,17 +77,17 @@ | EApp (e1, e2) => parenIf par (box [p_exp env e1, space, p_exp' true env e2]) - | EAbs (x, t, e) => parenIf par (box [string "fn", - space, - string x, - space, - string ":", - space, - p_typ env t, - space, - string "=>", - space, - p_exp (E.pushERel env x t) e]) + | EAbs (x, t, _, e) => parenIf par (box [string "fn", + space, + string x, + space, + string ":", + space, + p_typ env t, + space, + string "=>", + space, + p_exp (E.pushERel env x t) e]) | ERecord xes => box [string "{", p_list (fn (x, e) =>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mono_util.sig Tue Jun 10 15:56:33 2008 -0400 @@ -0,0 +1,118 @@ +(* Copyright (c) 2008, Adam Chlipala + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - The names of contributors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *) + +signature MONO_UTIL = sig + +structure Typ : sig + val mapfold : (Mono.typ', 'state, 'abort) Search.mapfolder + -> (Mono.typ, 'state, 'abort) Search.mapfolder + + val map : (Mono.typ' -> Mono.typ') + -> Mono.typ -> Mono.typ + + val fold : (Mono.typ' * 'state -> 'state) + -> 'state -> Mono.typ -> 'state + + val exists : (Mono.typ' -> bool) -> Mono.typ -> bool +end + +structure Exp : sig + datatype binder = + NamedT of string * int * Mono.typ option + | RelE of string * Mono.typ + | NamedE of string * int * Mono.typ * Mono.exp option + + val mapfoldB : {typ : (Mono.typ', 'state, 'abort) Search.mapfolder, + exp : ('typtext, Mono.exp', 'state, 'abort) Search.mapfolderB, + bind : 'typtext * binder -> 'typtext} + -> ('typtext, Mono.exp, 'state, 'abort) Search.mapfolderB + val mapfold : {typ : (Mono.typ', 'state, 'abort) Search.mapfolder, + exp : (Mono.exp', 'state, 'abort) Search.mapfolder} + -> (Mono.exp, 'state, 'abort) Search.mapfolder + + val map : {typ : Mono.typ' -> Mono.typ', + exp : Mono.exp' -> Mono.exp'} + -> Mono.exp -> Mono.exp + val mapB : {typ : Mono.typ' -> Mono.typ', + exp : 'typtext -> Mono.exp' -> Mono.exp', + bind : 'typtext * binder -> 'typtext} + -> 'typtext -> (Mono.exp -> Mono.exp) + + val fold : {typ : Mono.typ' * 'state -> 'state, + exp : Mono.exp' * 'state -> 'state} + -> 'state -> Mono.exp -> 'state + + val exists : {typ : Mono.typ' -> bool, + exp : Mono.exp' -> bool} -> Mono.exp -> bool +end + +structure Decl : sig + datatype binder = datatype Exp.binder + + val mapfoldB : {typ : (Mono.typ', 'state, 'abort) Search.mapfolder, + exp : ('typtext, Mono.exp', 'state, 'abort) Search.mapfolderB, + decl : ('typtext, Mono.decl', 'state, 'abort) Search.mapfolderB, + bind : 'typtext * binder -> 'typtext} + -> ('typtext, Mono.decl, 'state, 'abort) Search.mapfolderB + val mapfold : {typ : (Mono.typ', 'state, 'abort) Search.mapfolder, + exp : (Mono.exp', 'state, 'abort) Search.mapfolder, + decl : (Mono.decl', 'state, 'abort) Search.mapfolder} + -> (Mono.decl, 'state, 'abort) Search.mapfolder + + val fold : {typ : Mono.typ' * 'state -> 'state, + exp : Mono.exp' * 'state -> 'state, + decl : Mono.decl' * 'state -> 'state} + -> 'state -> Mono.decl -> 'state +end + +structure File : sig + datatype binder = datatype Exp.binder + + val mapfoldB : {typ : (Mono.typ', 'state, 'abort) Search.mapfolder, + exp : ('typtext, Mono.exp', 'state, 'abort) Search.mapfolderB, + decl : ('typtext, Mono.decl', 'state, 'abort) Search.mapfolderB, + bind : 'typtext * binder -> 'typtext} + -> ('typtext, Mono.file, 'state, 'abort) Search.mapfolderB + + val mapfold : {typ : (Mono.typ', 'state, 'abort) Search.mapfolder, + exp : (Mono.exp', 'state, 'abort) Search.mapfolder, + decl : (Mono.decl', 'state, 'abort) Search.mapfolder} + -> (Mono.file, 'state, 'abort) Search.mapfolder + + val mapB : {typ : Mono.typ' -> Mono.typ', + exp : 'typtext -> Mono.exp' -> Mono.exp', + decl : 'typtext -> Mono.decl' -> Mono.decl', + bind : 'typtext * binder -> 'typtext} + -> 'typtext -> Mono.file -> Mono.file + + val fold : {typ : Mono.typ' * 'state -> 'state, + exp : Mono.exp' * 'state -> 'state, + decl : Mono.decl' * 'state -> 'state} + -> 'state -> Mono.file -> 'state +end + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mono_util.sml Tue Jun 10 15:56:33 2008 -0400 @@ -0,0 +1,263 @@ +(* Copyright (c) 2008, Adam Chlipala + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - The names of contributors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *) + +structure MonoUtil :> MONO_UTIL = struct + +open Mono + +structure S = Search + +structure Typ = struct + +fun mapfold fc = + let + fun mft c acc = + S.bindP (mft' c acc, fc) + + and mft' (cAll as (c, loc)) = + case c of + TFun (t1, t2) => + S.bind2 (mft t1, + fn t1' => + S.map2 (mft t2, + fn t2' => + (TFun (t1', t2'), loc))) + | TRecord xts => + S.map2 (ListUtil.mapfold (fn (x, t) => + S.map2 (mft t, + fn t' => + (x, t'))) + xts, + fn xts' => (TRecord xts', loc)) + | TNamed _ => S.return2 cAll + in + mft + end + +fun map typ c = + case mapfold (fn c => fn () => S.Continue (typ c, ())) c () of + S.Return () => raise Fail "Mono_util.Typ.map" + | S.Continue (c, ()) => c + +fun fold typ s c = + case mapfold (fn c => fn s => S.Continue (c, typ (c, s))) c s of + S.Continue (_, s) => s + | S.Return _ => raise Fail "MonoUtil.Typ.fold: Impossible" + +fun exists typ k = + case mapfold (fn c => fn () => + if typ c then + S.Return () + else + S.Continue (c, ())) k () of + S.Return _ => true + | S.Continue _ => false + +end + +structure Exp = struct + +datatype binder = + NamedT of string * int * typ option + | RelE of string * typ + | NamedE of string * int * typ * exp option + +fun mapfoldB {typ = fc, exp = fe, bind} = + let + val mft = Typ.mapfold fc + + fun mfe ctx e acc = + S.bindP (mfe' ctx e acc, fe ctx) + + and mfe' ctx (eAll as (e, loc)) = + case e of + EPrim _ => S.return2 eAll + | ERel _ => S.return2 eAll + | ENamed _ => S.return2 eAll + | EApp (e1, e2) => + S.bind2 (mfe ctx e1, + fn e1' => + S.map2 (mfe ctx e2, + fn e2' => + (EApp (e1', e2'), loc))) + | EAbs (x, dom, ran, e) => + S.bind2 (mft dom, + fn dom' => + S.bind2 (mft ran, + fn ran' => + S.map2 (mfe (bind (ctx, RelE (x, dom'))) e, + fn e' => + (EAbs (x, dom', ran', e'), loc)))) + + | ERecord xes => + S.map2 (ListUtil.mapfold (fn (x, e) => + S.map2 (mfe ctx e, + fn e' => + (x, e'))) + xes, + fn xes' => + (ERecord xes', loc)) + | EField (e, x) => + S.map2 (mfe ctx e, + fn e' => + (EField (e', x), loc)) + in + mfe + end + +fun mapfold {typ = fc, exp = fe} = + mapfoldB {typ = fc, + exp = fn () => fe, + bind = fn ((), _) => ()} () + +fun mapB {typ, exp, bind} ctx e = + case mapfoldB {typ = fn c => fn () => S.Continue (typ c, ()), + exp = fn ctx => fn e => fn () => S.Continue (exp ctx e, ()), + bind = bind} ctx e () of + S.Continue (e, ()) => e + | S.Return _ => raise Fail "MonoUtil.Exp.mapB: Impossible" + +fun map {typ, exp} e = + case mapfold {typ = fn c => fn () => S.Continue (typ c, ()), + exp = fn e => fn () => S.Continue (exp e, ())} e () of + S.Return () => raise Fail "Mono_util.Exp.map" + | S.Continue (e, ()) => e + +fun fold {typ, exp} s e = + case mapfold {typ = fn c => fn s => S.Continue (c, typ (c, s)), + exp = fn e => fn s => S.Continue (e, exp (e, s))} e s of + S.Continue (_, s) => s + | S.Return _ => raise Fail "MonoUtil.Exp.fold: Impossible" + +fun exists {typ, exp} k = + case mapfold {typ = fn c => fn () => + if typ c then + S.Return () + else + S.Continue (c, ()), + exp = fn e => fn () => + if exp e then + S.Return () + else + S.Continue (e, ())} k () of + S.Return _ => true + | S.Continue _ => false + +end + +structure Decl = struct + +datatype binder = datatype Exp.binder + +fun mapfoldB {typ = fc, exp = fe, decl = fd, bind} = + let + val mft = Typ.mapfold fc + + val mfe = Exp.mapfoldB {typ = fc, exp = fe, bind = bind} + + fun mfd ctx d acc = + S.bindP (mfd' ctx d acc, fd ctx) + + and mfd' ctx (dAll as (d, loc)) = + case d of + DVal (x, n, t, e) => + S.bind2 (mft t, + fn t' => + S.map2 (mfe ctx e, + fn e' => + (DVal (x, n, t', e'), loc))) + in + mfd + end + +fun mapfold {typ = fc, exp = fe, decl = fd} = + mapfoldB {typ = fc, + exp = fn () => fe, + decl = fn () => fd, + bind = fn ((), _) => ()} () + +fun fold {typ, exp, decl} s d = + case mapfold {typ = fn c => fn s => S.Continue (c, typ (c, s)), + exp = fn e => fn s => S.Continue (e, exp (e, s)), + decl = fn d => fn s => S.Continue (d, decl (d, s))} d s of + S.Continue (_, s) => s + | S.Return _ => raise Fail "MonoUtil.Decl.fold: Impossible" + +end + +structure File = struct + +datatype binder = datatype Exp.binder + +fun mapfoldB (all as {bind, ...}) = + let + val mfd = Decl.mapfoldB all + + fun mff ctx ds = + case ds of + nil => S.return2 nil + | d :: ds' => + S.bind2 (mfd ctx d, + fn d' => + let + val b = + case #1 d' of + DVal (x, n, t, e) => NamedE (x, n, t, SOME e) + val ctx' = bind (ctx, b) + in + S.map2 (mff ctx' ds', + fn ds' => + d' :: ds') + end) + in + mff + end + +fun mapfold {typ = fc, exp = fe, decl = fd} = + mapfoldB {typ = fc, + exp = fn () => fe, + decl = fn () => fd, + bind = fn ((), _) => ()} () + +fun mapB {typ, exp, decl, bind} ctx ds = + case mapfoldB {typ = fn c => fn () => S.Continue (typ c, ()), + exp = fn ctx => fn e => fn () => S.Continue (exp ctx e, ()), + decl = fn ctx => fn d => fn () => S.Continue (decl ctx d, ()), + bind = bind} ctx ds () of + S.Continue (ds, ()) => ds + | S.Return _ => raise Fail "MonoUtil.File.mapB: Impossible" + +fun fold {typ, exp, decl} s d = + case mapfold {typ = fn c => fn s => S.Continue (c, typ (c, s)), + exp = fn e => fn s => S.Continue (e, exp (e, s)), + decl = fn d => fn s => S.Continue (d, decl (d, s))} d s of + S.Continue (_, s) => s + | S.Return _ => raise Fail "MonoUtil.File.fold: Impossible" + +end + +end
--- a/src/monoize.sml Tue Jun 10 13:14:45 2008 -0400 +++ b/src/monoize.sml Tue Jun 10 15:56:33 2008 -0400 @@ -86,8 +86,8 @@ | L.ERel n => (L'.ERel n, loc) | L.ENamed n => (L'.ENamed n, loc) | L.EApp (e1, e2) => (L'.EApp (monoExp env e1, monoExp env e2), loc) - | L.EAbs (x, t, e) => - (L'.EAbs (x, monoType env t, monoExp (Env.pushERel env x t) e), loc) + | L.EAbs (x, dom, ran, e) => + (L'.EAbs (x, monoType env dom, monoType env ran, monoExp (Env.pushERel env x dom) e), loc) | L.ECApp _ => poly () | L.ECAbs _ => poly ()
--- a/src/reduce.sml Tue Jun 10 13:14:45 2008 -0400 +++ b/src/reduce.sml Tue Jun 10 15:56:33 2008 -0400 @@ -139,7 +139,7 @@ (_, _, SOME e') => #1 e' | _ => e) - | EApp ((EAbs (_, _, e1), loc), e2) => + | EApp ((EAbs (_, _, _, e1), loc), e2) => #1 (reduceExp env (subExpInExp (0, e2) e1)) | ECApp ((ECAbs (_, _, e1), loc), c) => #1 (reduceExp env (subConInExp (0, c) e1))
--- a/src/sources Tue Jun 10 13:14:45 2008 -0400 +++ b/src/sources Tue Jun 10 15:56:33 2008 -0400 @@ -60,11 +60,28 @@ monoize.sig monoize.sml +mono_util.sig +mono_util.sml + mono_env.sig mono_env.sml mono_print.sig mono_print.sml +flat.sml + +flat_util.sig +flat_util.sml + +flat_env.sig +flat_env.sml + +flat_print.sig +flat_print.sml + +cloconv.sig +cloconv.sml + compiler.sig compiler.sml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/cloconv.lac Tue Jun 10 15:56:33 2008 -0400 @@ -0,0 +1,1 @@ +val main = fn x : int => x