Created
          October 19, 2016 16:47 
        
      - 
      
- 
        Save myuon/ed48542406fc8b2bb839903aebeade8b to your computer and use it in GitHub Desktop. 
    Cousineau G., Curien P.-L., Mauny M. The categorical abstract machine. — LNCS, 201, Functional programming languages computer architecture.-- 1985, pp.~50-64.
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | type expr = | |
| | MLplus | MLequal | MLfst | MLsnd | |
| | MLint of int | |
| | MLbool of bool | |
| | MLvar of string | |
| | MLcond of expr * expr * expr | |
| | MLpair of expr * expr | |
| | MLin of dec * expr | |
| | MLabstr of pat * expr | |
| | MLapp of expr * expr | |
| and dec = | |
| | MLlet of pat * expr | |
| | MLletrec of pat * expr | |
| and pat = | |
| | Nullpat | |
| | Varpat of string | |
| | Pairpat of pat * pat;; | |
| type instruction = | |
| | Plus | Eq | |
| | Quote of value | |
| | Fst | Snd | Cons | Wind | |
| | Push | Swap | Return | App | |
| | Cur of code | |
| | Branch of code * code | |
| and value = | |
| | Nullvalue | |
| | Int of int | |
| | Bool of bool | |
| | Pair of value * value | |
| | Closure of code * value | |
| and code = instruction list;; | |
| type stackelem = Val of value | |
| | Code of code;; | |
| type stack = stackelem list;; | |
| type config = value ref * code * stack;; | |
| let rec exec : config -> config = fun w -> | |
| match w with | |
| | ({ contents = Pair(x,y) },(Fst::c),d) -> exec(ref x,c,d) | |
| | ({ contents = Pair(x,y) },(Snd::c),d) -> exec(ref y,c,d) | |
| | (x,(Cons::c),(Val y)::d) -> exec(ref (Pair(y,!x)),c,d) | |
| | (x,(Wind::c),((Val (Pair(y,z) as u))::d)) -> ref z := !x; exec(ref u,c,d) | |
| | ({ contents = x },(Push::c),d) -> exec(ref x,c,(Val x)::d) | |
| | ({ contents = x },(Swap::c),(Val y::d)) -> exec(ref y,c,(Val x)::d) | |
| | (t,((Quote v)::c),d) -> exec(ref v,c,d) | |
| | ({ contents = Pair(Closure(x,y),z) },(App::c),d) -> exec(ref (Pair(y,z)),x,(Code c)::d) | |
| | ({ contents = Bool(b) },((Branch(c1,c2))::c),((Val x)::d)) -> exec(ref x, (if b then c1 else c2), (Code c)::d) | |
| | ({ contents = Pair(Int m,Int n) },(Plus::c),d) -> exec(ref (Int(m+n)),c,d) | |
| | ({ contents = Pair(Int m,Int n) },(Eq::c),d) -> exec(ref (Bool(m=n)),c,d) | |
| | ({ contents = x },((Cur c1)::c),d) -> exec(ref (Closure(c1,x)),c,d) | |
| | ({ contents = x },(Return::c),((Code c')::d)) -> exec(ref x,c',d) | |
| | config -> config;; | |
| let exec_code : code -> config = fun cs -> exec(ref Nullvalue,cs,[]);; | |
| let rec access : string -> pat -> code = fun id w -> | |
| match w with | |
| | Nullpat -> failwith "nullpat" | |
| | (Varpat x) -> if x = id then [] else failwith "x /= id" | |
| | (Pairpat (x1,x2)) -> try (Snd::(access id x2)) with Failure(_) -> (Fst :: (access id x1));; | |
| let rec compile : pat -> expr -> code = fun pat w -> | |
| match w with | |
| | (MLint n) -> [Quote (Int n)] | |
| | (MLbool b) -> [Quote (Bool b)] | |
| | (MLvar v) -> access v pat | |
| | (MLcond(e1,e2,e3)) -> | |
| [Push] @ (compile pat e1) @ | |
| [Branch((compile pat e2) @ [Return], (compile pat e3) @ [Return])] | |
| | (MLpair(e1,e2)) -> | |
| [Push] @ (compile pat e1) @ [Swap] @ (compile pat e2) @ [Cons] | |
| | (MLin(MLlet(p,e1),e2)) -> let pat' = Pairpat(pat,p) in | |
| [Push] @ (compile pat e1) @ [Cons] @ (compile pat' e2) | |
| | (MLin(MLletrec(p,e1),e2)) -> let pat' = Pairpat(pat,p) in | |
| [Push; Quote Nullvalue; Cons; Push] @ (compile pat' e1) @ | |
| [Swap; Wind] @ (compile pat' e2) | |
| | (MLabstr(p,e)) -> let pat' = Pairpat(pat,p) in | |
| [Cur ((compile pat' e) @ [Return])] | |
| | (MLapp(e1,e2)) -> | |
| if is_constant e1 then (compile pat e2) @ (trans_constant e1) | |
| else [Push] @ (compile pat e1) @ [Swap] @ (compile pat e2) @ [Cons; App] | |
| | e -> | |
| if is_constant e then [Cur (Snd :: trans_constant e)] else failwith "compile" | |
| and is_constant e = List.mem e [MLplus; MLequal; MLfst; MLsnd] | |
| and trans_constant = fun w -> | |
| match w with | |
| | MLplus -> [Plus] | |
| | MLequal -> [Eq] | |
| | MLfst -> [Fst] | |
| | MLsnd -> [Snd] | |
| | _ -> failwith "trans_constant";; | |
| let run : expr -> config = fun e -> exec_code(compile Nullpat e);; | |
| (* | |
| let x = 5 in | |
| let z y = y + x in | |
| let x = 1 in | |
| let r = z x in r + r ## 12 | |
| *) | |
| run( | |
| MLin(MLlet(Varpat "x", MLint 5), | |
| MLin(MLlet(Varpat "z", MLabstr(Varpat "y",MLapp(MLplus, MLpair(MLvar "y", MLvar "x")))), | |
| MLin(MLlet(Varpat "x", MLint 1), | |
| MLin(MLlet(Varpat "r", MLapp(MLvar "z", MLvar "x")), | |
| MLapp(MLplus, MLpair(MLvar "r", MLvar "r")) | |
| )) | |
| )) | |
| );; | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment