[MLton] HOL's Moscow ML implementation, and pushing MLton to
emulate it
Daniel C. Wang
danwang@CS.Princeton.EDU
Fri, 08 Apr 2005 22:58:22 -0400
This is a multi-part message in MIME format.
--------------090607040003080506040707
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Attached is SML file that sketchs how to do the interoperation expressed as
a source to source translation of code to be linked into the interpter.
It deals with recursive polymorphic structures.
Each coercion between the generic and hosted representation is constant time.
--------------090607040003080506040707
Content-Type: text/plain;
name="eval.sml"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="eval.sml"
(* Generic Interpreter *)
structure Eval =
struct
type var = string
datatype exp =
Val of value
| App of exp * exp
| Lam of var * exp
| Var of var
and value =
I of int
| P of value * value
| F of value -> value
| A of unit -> value (* abstract value *) (* using thunk to simulate existential type *)
fun empty _ = raise (Fail "not found")
fun bind (env,x,v) y =
if x = y then v else env y
fun eval env (Val (A av)) = (av ())
| eval env (Val v) = v
| eval env (App(e1,e2)) =
(case (eval env e1,eval env e2) of
(F f,v) => f v
| _ => raise (Fail "bad app"))
| eval env (Lam (x,e)) =
(F (fn v => eval (bind (env,x,v)) e))
| eval env (Var x) = (env x)
end
(* Polymorphic Input source program to be linked into interpret *)
structure Lst =
struct
datatype 'a list = Nil | Cons of ('a * 'a list)
fun length Nil = 0
| length (Cons(_,xs)) = 1 + length xs
fun sum Nil = 0
| sum (Cons(x,xs)) = x + sum xs
fun mkLst 0 = Nil
| mkLst n = (Cons(n,mkLst (n-1)))
end
(* Produced via type-directed source translation of input source. *)
structure Lst =
struct
(* generic abstract interface *)
datatype ('a,'b) listF =
Nil
| Cons of ('a * 'b)
fun lengthF unwrap Nil = 0
| lengthF unwrap (Cons(_,b)) = 1 + lengthF unwrap (unwrap b)
fun sumF unwrap Nil = 0
| sumF unwrap (Cons(x,xs)) = x + sumF unwrap (unwrap xs)
fun mkLstF wrap 0 = wrap Nil
| mkLstF wrap n = wrap (Cons(n,mkLstF wrap (n-1)))
(* exported to the normal compiled "host" SML code that never interacts with our interpret *)
datatype 'a list = Fix of ('a,'a list) listF
fun length (Fix x) = lengthF (fn Fix x => x) x
fun sum (Fix x) = sumF (fn Fix x => x) x
fun mkLst x = mkLstF Fix x
end
(* generated automatically *)
structure InitEnv :> sig
val init_env : Eval.var -> Eval.value
end =
struct
open Lst
open Eval
(* each coercion is constant time *)
fun wrapLst wrap Nil = I 0
| wrapLst wrap (Cons(x,xs)) = P(wrap x,xs)
fun unwrapLst unwrap (I 0) = Nil
| unwrapLst unwrap (P(x,xs)) = Cons(unwrap x,xs)
| unwrapLst unwrap (A av) = unwrapLst unwrap (av())
| unwrapLst unwrap _ = raise (Fail "bad list")
fun wrapInt i = I i
fun unwrapInt (I i) = i
| unwrapInt (A av) = unwrapInt (av ())
| unwrapInt _ = raise (Fail "bad int")
fun id x = x
val interp_length = F (fn x => wrapInt (lengthF (unwrapLst id) (unwrapLst id x)))
val interp_sum = F (fn x => wrapInt (sumF (unwrapLst unwrapInt) (unwrapLst unwrapInt x)))
val interp_mkLst = F (fn x => (mkLstF (wrapLst wrapInt) (unwrapInt x)))
(* coerce a native host list to an interp list *)
fun interpLst wrap (Fix Nil) = (I 0)
| interpLst wrap (Fix (Cons(x,xs))) = (P(wrap x,A (fn () => interpLst wrap xs)))
fun bind_lst xs = List.foldl (fn ((x,v),env) => bind (env,x,v)) empty xs
val init_env =
bind_lst [("length",interp_length),
("sum",interp_sum),
("mkLst",interp_mkLst),
("l",interpLst wrapInt (mkLst 10))]
end
structure Example =
struct
open Eval
val prog1 = App(Var "length",Var "l")
val prog2 = App(Var "sum",Var "l")
val prog3 = App(Var "length",App(Var "mkLst",Val (I 10)))
val prog4 = App(Var "sum",App(Var "mkLst",Val (I 10)))
fun run p = Eval.eval InitEnv.init_env p
end
--------------090607040003080506040707--