main.mli1: val limit : int ref 2: val string : string -> unit 3: val file : string -> unit
main.ml1: let limit = ref 1000 2: 3: let rec iter n e = (* 最適化処理をくりかえす *) 4: Format.eprintf "iteration %d@." n; 5: if n = 0 then e else 6: let e' = Elim.f (ConstFold.f (Inline.f (Assoc.f (Beta.f e)))) in 7: if e = e' then e else 8: iter (n - 1) e' 9: 10: let lexbuf outchan l = (* バッファをコンパイルしてチャンネルへ出力する *) 11: Id.counter := 0; 12: Typing.extenv := M.empty; 13: Emit.f outchan 14: (RegAlloc.f 15: (Simm13.f 16: (Virtual.f 17: (Closure.f 18: (iter !limit 19: (Alpha.f 20: (KNormal.f 21: (Typing.f 22: (Parser.exp Lexer.token l))))))))) 23: 24: let string s = lexbuf stdout (Lexing.from_string s) (* 文字列をコンパイルして標準出力に表示する *) 25: 26: let file f = (* ファイルをコンパイルしてファイルに出力する *) 27: let inchan = open_in (f ^ ".ml") in 28: let outchan = open_out (f ^ ".s") in 29: try 30: lexbuf outchan (Lexing.from_channel inchan); 31: close_in inchan; 32: close_out outchan; 33: with e -> (close_in inchan; close_out outchan; raise e) 34: 35: let () = (* ここからコンパイラの実行が開始される *) 36: let files = ref [] in 37: Arg.parse 38: [("-inline", Arg.Int(fun i -> Inline.threshold := i), "maximum size of functions inlined"); 39: ("-iter", Arg.Int(fun i -> limit := i), "maximum number of optimizations iterated")] 40: (fun s -> files := !files @ [s]) 41: ("Mitou Min-Caml Compiler (C) Eijiro Sumii\n" ^ 42: Printf.sprintf "usage: %s [-inline m] [-iter n] ...filenames without \".ml\"..." Sys.argv.(0)); 43: List.iter 44: (fun f -> ignore (file f)) 45: !files
id.ml1: type t = string (* 変数の名前 *) 2: type l = L of string (* トップレベル関数やグローバル配列のラベル *) 3: 4: let rec pp_list = function 5: | [] -> "" 6: | [x] -> x 7: | x :: xs -> x ^ " " ^ pp_list xs 8: 9: let counter = ref 0 10: let genid s = 11: incr counter; 12: Printf.sprintf "%s.%d" s !counter 13: 14: let rec id_of_typ = function 15: | Type.Unit -> "u" 16: | Type.Bool -> "b" 17: | Type.Int -> "i" 18: | Type.Float -> "d" 19: | Type.Fun _ -> "f" 20: | Type.Tuple _ -> "t" 21: | Type.Array _ -> "a" 22: | Type.Var _ -> assert false 23: let gentmp typ = 24: incr counter; 25: Printf.sprintf "T%s%d" (id_of_typ typ) !counter
m.ml1: (* customized version of Map *) 2: 3: module M = 4: Map.Make 5: (struct 6: type t = Id.t 7: let compare = compare 8: end) 9: include M 10: 11: let add_list xys env = List.fold_left (fun env (x, y) -> add x y env) env xys 12: let add_list2 xs ys env = List.fold_left2 (fun env x y -> add x y env) env xs ys
s.ml1: (* customized version of Set *) 2: 3: module S = 4: Set.Make 5: (struct 6: type t = Id.t 7: let compare = compare 8: end) 9: include S 10: 11: let of_list l = List.fold_left (fun s e -> add e s) empty l
syntax.ml1: type t = (* MinCamlの構文を表現するデータ型 *) 2: | Unit 3: | Bool of bool 4: | Int of int 5: | Float of float 6: | Not of t 7: | Neg of t 8: | Add of t * t 9: | Sub of t * t 10: | FNeg of t 11: | FAdd of t * t 12: | FSub of t * t 13: | FMul of t * t 14: | FDiv of t * t 15: | Eq of t * t 16: | NEq of t * t 17: | Lt of t * t 18: | LE of t * t 19: | If of t * t * t 20: | Let of (Id.t * Type.t) * t * t 21: | Var of Id.t 22: | LetRec of fundef list * t (* mutual recursion *) 23: | App of t * t list 24: | Tuple of t list 25: | LetTuple of (Id.t * Type.t) list * t * t 26: | Array of t * t 27: | Get of t * t 28: | Put of t * t * t 29: and fundef = { name : Id.t * Type.t; args : (Id.t * Type.t) list; body : t }
type.ml1: type t = (* MinCamlの型を表現するデータ型 *) 2: | Unit 3: | Bool 4: | Int 5: | Float 6: | Fun of t list * t (* arguments are uncurried *) 7: | Tuple of t list 8: | Array of t 9: | Var of t option ref 10: 11: let gentyp () = Var(ref None) (* 新しい型変数を作る *)
parser.mly1: %{ 2: (* parserが利用する変数、関数、型などの定義 *) 3: open Syntax 4: let addtyp x = (x, Type.gentyp ()) 5: %} 6: 7: /* 字句を表すデータ型の定義 */ 8: %token <bool> BOOL 9: %token <int> INT 10: %token <float> FLOAT 11: %token NOT 12: %token MINUS 13: %token PLUS 14: %token MINUS_DOT 15: %token PLUS_DOT 16: %token AST_DOT 17: %token SLASH_DOT 18: %token EQUAL 19: %token LESS_GREATER 20: %token LESS_EQUAL 21: %token GREATER_EQUAL 22: %token LESS 23: %token GREATER 24: %token IF 25: %token THEN 26: %token ELSE 27: %token <Id.t> IDENT 28: %token LET 29: %token IN 30: %token REC 31: %token AND 32: %token COMMA 33: %token ARRAY_CREATE 34: %token DOT 35: %token LESS_MINUS 36: %token SEMICOLON 37: %token LPAREN 38: %token RPAREN 39: %token EOF 40: 41: /* 優先順位とassociativityの定義(低い方から高い方へ) */ 42: %right prec_let 43: %right SEMICOLON 44: %right prec_if 45: %right LESS_MINUS 46: %left COMMA 47: %left EQUAL LESS_GREATER LESS GREATER LESS_EQUAL GREATER_EQUAL 48: %left PLUS MINUS PLUS_DOT MINUS_DOT 49: %left AST_DOT SLASH_DOT 50: %right prec_unary_minus 51: %left prec_app 52: %left DOT 53: 54: /* 開始記号の定義 */ 55: %type <Syntax.t> exp 56: %start exp 57: 58: %% 59: 60: simple_exp: /* 括弧をつけなくても関数の引数になれる式 */ 61: | LPAREN exp RPAREN 62: { $2 } 63: | LPAREN RPAREN 64: { Unit } 65: | BOOL 66: { Bool($1) } 67: | INT 68: { Int($1) } 69: | FLOAT 70: { Float($1) } 71: | IDENT 72: { Var($1) } 73: | simple_exp DOT LPAREN exp RPAREN 74: { Get($1, $4) } 75: 76: exp: /* 一般の式 */ 77: | simple_exp 78: { $1 } 79: | NOT exp 80: %prec prec_app 81: { Not($2) } 82: | MINUS exp 83: %prec prec_unary_minus 84: { Neg($2) } 85: | exp PLUS exp /* 足し算を構文解析するルール */ 86: { Add($1, $3) } 87: | exp MINUS exp 88: { Sub($1, $3) } 89: | exp EQUAL exp 90: { Eq($1, $3) } 91: | exp LESS_GREATER exp 92: { NEq($1, $3) } 93: | exp LESS exp 94: { Lt($1, $3) } 95: | exp GREATER exp 96: { Lt($3, $1) } 97: | exp LESS_EQUAL exp 98: { LE($1, $3) } 99: | exp GREATER_EQUAL exp 100: { LE($3, $1) } 101: | IF exp THEN exp ELSE exp 102: %prec prec_if 103: { If($2, $4, $6) } 104: | MINUS_DOT exp 105: %prec prec_unary_minus 106: { FNeg($2) } 107: | exp PLUS_DOT exp 108: { FAdd($1, $3) } 109: | exp MINUS_DOT exp 110: { FSub($1, $3) } 111: | exp AST_DOT exp 112: { FMul($1, $3) } 113: | exp SLASH_DOT exp 114: { FDiv($1, $3) } 115: | LET IDENT EQUAL exp IN exp 116: %prec prec_let 117: { Let(addtyp $2, $4, $6) } 118: | LET REC fundefs IN exp 119: %prec prec_let 120: { LetRec($3, $5) } 121: | exp actual_args 122: %prec prec_app 123: { App($1, $2) } 124: | elems 125: { Tuple($1) } 126: | LET LPAREN pat RPAREN EQUAL exp IN exp 127: { LetTuple($3, $6, $8) } 128: | simple_exp DOT LPAREN exp RPAREN LESS_MINUS exp 129: { Put($1, $4, $7) } 130: | exp SEMICOLON exp 131: { Let((Id.gentmp Type.Unit, Type.Unit), $1, $3) } 132: | ARRAY_CREATE simple_exp simple_exp 133: %prec prec_app 134: { Array($2, $3) } 135: | error 136: { failwith 137: (Printf.sprintf "parse error near characters %d-%d" 138: (Parsing.symbol_start ()) 139: (Parsing.symbol_end ())) } 140: 141: fundefs: 142: | fundef AND fundefs 143: { $1 :: $3 } 144: | fundef 145: { [$1] } 146: 147: fundef: 148: | IDENT formal_args EQUAL exp 149: { { name = addtyp $1; args = $2; body = $4 } } 150: 151: formal_args: 152: | IDENT formal_args 153: { addtyp $1 :: $2 } 154: | IDENT 155: { [addtyp $1] } 156: 157: actual_args: 158: | actual_args simple_exp 159: %prec prec_app 160: { $1 @ [$2] } 161: | simple_exp 162: %prec prec_app 163: { [$1] } 164: 165: elems: 166: | elems COMMA exp 167: { $1 @ [$3] } 168: | exp COMMA exp 169: { [$1; $3] } 170: 171: pat: 172: | pat COMMA IDENT 173: { $1 @ [addtyp $3] } 174: | IDENT COMMA IDENT 175: { [addtyp $1; addtyp $3] }
lexer.mll1: { 2: (* lexerが利用する変数、関数、型などの定義 *) 3: open Parser 4: open Type 5: } 6: 7: (* 正規表現の略記 *) 8: let space = [' ' '\t' '\n' '\r'] 9: let digit = ['0'-'9'] 10: let lower = ['a'-'z'] 11: let upper = ['A'-'Z'] 12: 13: rule token = parse 14: | space+ 15: { token lexbuf } 16: | "(*" 17: { comment lexbuf; (* ネストしたコメントのためのトリック *) 18: token lexbuf } 19: | '(' 20: { LPAREN } 21: | ')' 22: { RPAREN } 23: | "true" 24: { BOOL(true) } 25: | "false" 26: { BOOL(false) } 27: | "not" 28: { NOT } 29: | '-'? digit+ (* 整数を字句解析するルール *) 30: { INT(int_of_string (Lexing.lexeme lexbuf)) } 31: | '-'? digit+ ('.' digit*)? (['e' 'E'] ['+' '-']? digit+)? 32: { FLOAT(float_of_string (Lexing.lexeme lexbuf)) } 33: | '-' (* -.より後回しにしなくても良い? 最長一致? *) 34: { MINUS } 35: | '+' (* +.より後回しにしなくても良い? 最長一致? *) 36: { PLUS } 37: | "-." 38: { MINUS_DOT } 39: | "+." 40: { PLUS_DOT } 41: | "*." 42: { AST_DOT } 43: | "/." 44: { SLASH_DOT } 45: | '=' 46: { EQUAL } 47: | "<>" 48: { LESS_GREATER } 49: | "<=" 50: { LESS_EQUAL } 51: | ">=" 52: { GREATER_EQUAL } 53: | '<' 54: { LESS } 55: | '>' 56: { GREATER } 57: | "if" 58: { IF } 59: | "then" 60: { THEN } 61: | "else" 62: { ELSE } 63: | "let" 64: { LET } 65: | "in" 66: { IN } 67: | "rec" 68: { REC } 69: | "and" 70: { AND } 71: | ',' 72: { COMMA } 73: | '_' 74: { IDENT(Id.gentmp Type.Unit) } 75: | "Array.create" (* [XX] ad hoc *) 76: { ARRAY_CREATE } 77: | '.' 78: { DOT } 79: | "<-" 80: { LESS_MINUS } 81: | ';' 82: { SEMICOLON } 83: | eof 84: { EOF } 85: | lower (digit|lower|upper|'_')* (* 他の「予約語」より後でないといけない *) 86: { IDENT(Lexing.lexeme lexbuf) } 87: | _ 88: { failwith 89: (Printf.sprintf "unknown token %s near characters %d-%d" 90: (Lexing.lexeme lexbuf) 91: (Lexing.lexeme_start lexbuf) 92: (Lexing.lexeme_end lexbuf)) } 93: and comment = parse 94: | "*)" 95: { () } 96: | "(*" 97: { comment lexbuf; 98: comment lexbuf } 99: | eof 100: { Format.eprintf "warning: unterminated comment@." } 101: | _ 102: { comment lexbuf }
typing.mli1: exception Error of Syntax.t * Type.t * Type.t 2: val extenv : Type.t M.t ref 3: val f : Syntax.t -> Syntax.t
typing.ml1: (* type inference/reconstruction *) 2: 3: open Syntax 4: 5: exception Unify of Type.t * Type.t 6: exception Error of t * Type.t * Type.t 7: 8: let extenv = ref M.empty 9: 10: (* for pretty printing (and type normalization) *) 11: let rec deref_typ = function (* 型変数を中身でおきかえる関数 *) 12: | Type.Fun(t1s, t2) -> Type.Fun(List.map deref_typ t1s, deref_typ t2) 13: | Type.Tuple(ts) -> Type.Tuple(List.map deref_typ ts) 14: | Type.Array(t) -> Type.Array(deref_typ t) 15: | Type.Var({ contents = None } as r) -> 16: Format.eprintf "uninstantiated type variable detected; assuming int@."; 17: r := Some(Type.Int); 18: Type.Int 19: | Type.Var({ contents = Some(t) } as r) -> 20: let t' = deref_typ t in 21: r := Some(t'); 22: t' 23: | t -> t 24: let rec deref_id_typ (x, t) = (x, deref_typ t) 25: let rec deref_term = function 26: | Not(e) -> Not(deref_term e) 27: | Neg(e) -> Neg(deref_term e) 28: | Add(e1, e2) -> Add(deref_term e1, deref_term e2) 29: | Sub(e1, e2) -> Sub(deref_term e1, deref_term e2) 30: | Eq(e1, e2) -> Eq(deref_term e1, deref_term e2) 31: | NEq(e1, e2) -> NEq(deref_term e1, deref_term e2) 32: | Lt(e1, e2) -> Lt(deref_term e1, deref_term e2) 33: | LE(e1, e2) -> LE(deref_term e1, deref_term e2) 34: | FNeg(e) -> FNeg(deref_term e) 35: | FAdd(e1, e2) -> FAdd(deref_term e1, deref_term e2) 36: | FSub(e1, e2) -> FSub(deref_term e1, deref_term e2) 37: | FMul(e1, e2) -> FMul(deref_term e1, deref_term e2) 38: | FDiv(e1, e2) -> FDiv(deref_term e1, deref_term e2) 39: | If(e1, e2, e3) -> If(deref_term e1, deref_term e2, deref_term e3) 40: | Let(xt, e1, e2) -> Let(deref_id_typ xt, deref_term e1, deref_term e2) 41: | LetRec(fundefs, e2) -> 42: LetRec(List.map 43: (fun { name = xt; args = yts; body = e1 } -> 44: { name = deref_id_typ xt; 45: args = List.map deref_id_typ yts; 46: body = deref_term e1 }) 47: fundefs, 48: deref_term e2) 49: | App(e, es) -> App(deref_term e, List.map deref_term es) 50: | Tuple(es) -> Tuple(List.map deref_term es) 51: | LetTuple(xts, e1, e2) -> LetTuple(List.map deref_id_typ xts, deref_term e1, deref_term e2) 52: | Array(e1, e2) -> Array(deref_term e1, deref_term e2) 53: | Get(e1, e2) -> Get(deref_term e1, deref_term e2) 54: | Put(e1, e2, e3) -> Put(deref_term e1, deref_term e2, deref_term e3) 55: | e -> e 56: 57: let rec occur r1 = function (* occur check *) 58: | Type.Fun(t2s, t2) -> List.exists (occur r1) t2s || occur r1 t2 59: | Type.Tuple(t2s) -> List.exists (occur r1) t2s 60: | Type.Array(t2) -> occur r1 t2 61: | Type.Var(r2) when r1 == r2 -> true 62: | Type.Var({ contents = None }) -> false 63: | Type.Var({ contents = Some(t2) }) -> occur r1 t2 64: | _ -> false 65: 66: let rec unify t1 t2 = (* 型が合うように、型変数への代入をする *) 67: match t1, t2 with 68: | Type.Unit, Type.Unit | Type.Bool, Type.Bool | Type.Int, Type.Int | Type.Float, Type.Float -> () 69: | Type.Fun(t1s, t1'), Type.Fun(t2s, t2') -> 70: (try List.iter2 unify t1s t2s 71: with Invalid_argument("List.iter2") -> raise (Unify(t1, t2))); 72: unify t1' t2' 73: | Type.Tuple(t1s), Type.Tuple(t2s) -> 74: (try List.iter2 unify t1s t2s 75: with Invalid_argument("List.iter2") -> raise (Unify(t1, t2))) 76: | Type.Array(t1), Type.Array(t2) -> unify t1 t2 77: | Type.Var(r1), Type.Var(r2) when r1 == r2 -> () 78: | Type.Var({ contents = Some(t1') }), _ -> unify t1' t2 79: | _, Type.Var({ contents = Some(t2') }) -> unify t1 t2' 80: | Type.Var({ contents = None } as r1), _ -> (* 一方が未定義の型変数の場合 *) 81: if occur r1 t2 then raise (Unify(t1, t2)); 82: r1 := Some(t2) 83: | _, Type.Var({ contents = None } as r2) -> 84: if occur r2 t1 then raise (Unify(t1, t2)); 85: r2 := Some(t1) 86: | _, _ -> raise (Unify(t1, t2)) 87: 88: let rec g env e = (* 型推論ルーチン *) 89: try 90: match e with 91: | Unit -> Type.Unit 92: | Bool(_) -> Type.Bool 93: | Int(_) -> Type.Int 94: | Float(_) -> Type.Float 95: | Not(e) -> 96: unify Type.Bool (g env e); 97: Type.Bool 98: | Neg(e) -> 99: unify Type.Int (g env e); 100: Type.Int 101: | Add(e1, e2) | Sub(e1, e2) -> (* 足し算(と引き算)の型推論 *) 102: unify Type.Int (g env e1); 103: unify Type.Int (g env e2); 104: Type.Int 105: | FNeg(e) -> 106: unify Type.Float (g env e); 107: Type.Float 108: | FAdd(e1, e2) | FSub(e1, e2) | FMul(e1, e2) | FDiv(e1, e2) -> 109: unify Type.Float (g env e1); 110: unify Type.Float (g env e2); 111: Type.Float 112: | Eq(e1, e2) | NEq(e1, e2) | Lt(e1, e2) | LE(e1, e2) -> 113: unify (g env e1) (g env e2); 114: Type.Bool 115: | If(e1, e2, e3) -> 116: unify (g env e1) Type.Bool; 117: let t2 = g env e2 in 118: let t3 = g env e3 in 119: unify t2 t3; 120: t2 121: | Let((x, t), e1, e2) -> (* letの型推論 *) 122: unify t (g env e1); 123: g (M.add x t env) e2 124: | Var(x) when M.mem x env -> M.find x env (* 変数の型推論 *) 125: | Var(x) when M.mem x !extenv -> M.find x !extenv 126: | Var(x) -> (* 外部変数の型推論 *) 127: Format.eprintf "free variable %s assumed as external@." x; 128: let t = Type.gentyp () in 129: extenv := M.add x t !extenv; 130: t 131: | LetRec(fundefs, e2) -> (* let recの型推論 *) 132: let env = 133: M.add_list 134: (List.map (fun fundef -> fundef.name) fundefs) 135: env in 136: List.iter 137: (fun { name = (x, t); args = yts; body = e1 } -> 138: unify t (Type.Fun(List.map snd yts, g (M.add_list yts env) e1))) 139: fundefs; 140: g env e2 141: | App(e, es) -> (* 関数適用の型推論 *) 142: let t = Type.gentyp () in 143: unify (g env e) (Type.Fun(List.map (g env) es, t)); 144: t 145: | Tuple(es) -> Type.Tuple(List.map (g env) es) 146: | LetTuple(xts, e1, e2) -> 147: unify (Type.Tuple(List.map snd xts)) (g env e1); 148: g (M.add_list xts env) e2 149: | Array(e1, e2) -> (* must be a primitive for "polymorphic" typing *) 150: unify (g env e1) Type.Int; 151: Type.Array(g env e2) 152: | Get(e1, e2) -> 153: let t = Type.gentyp () in 154: unify (Type.Array(t)) (g env e1); 155: unify Type.Int (g env e2); 156: t 157: | Put(e1, e2, e3) -> 158: let t = g env e3 in 159: unify (Type.Array(t)) (g env e1); 160: unify Type.Int (g env e2); 161: Type.Unit 162: with Unify(t1, t2) -> raise (Error(deref_term e, deref_typ t1, deref_typ t2)) 163: 164: let f e = 165: extenv := M.empty; 166: (* 167: (match deref_typ (g M.empty e) with 168: | Type.Unit -> () 169: | _ -> Format.eprintf "warning: final result does not have type unit@."); 170: *) 171: (try unify Type.Unit (g M.empty e) 172: with Unify _ -> failwith "top level does not have type unit"); 173: extenv := M.map deref_typ !extenv; 174: deref_term e
kNormal.mli1: type t = 2: | Unit 3: | Int of int 4: | Float of float 5: | Neg of Id.t 6: | Add of Id.t * Id.t 7: | Sub of Id.t * Id.t 8: | FNeg of Id.t 9: | FAdd of Id.t * Id.t 10: | FSub of Id.t * Id.t 11: | FMul of Id.t * Id.t 12: | FDiv of Id.t * Id.t 13: | IfEq of Id.t * Id.t * t * t 14: | IfLE of Id.t * Id.t * t * t 15: | Let of (Id.t * Type.t) * t * t 16: | Var of Id.t 17: | LetRec of fundef list * t 18: | App of Id.t * Id.t list 19: | Tuple of Id.t list 20: | LetTuple of (Id.t * Type.t) list * Id.t * t 21: | Get of Id.t * Id.t 22: | Put of Id.t * Id.t * Id.t 23: | ExtArray of Id.t 24: | ExtFunApp of Id.t * Id.t list 25: and fundef = { name : Id.t * Type.t; args : (Id.t * Type.t) list; body : t } 26: 27: val fv : t -> S.t 28: val f : Syntax.t -> t
kNormal.ml1: (* give names to intermediate values (K-normalization) *) 2: 3: type t = (* K正規化後の式 *) 4: | Unit 5: | Int of int 6: | Float of float 7: | Neg of Id.t 8: | Add of Id.t * Id.t 9: | Sub of Id.t * Id.t 10: | FNeg of Id.t 11: | FAdd of Id.t * Id.t 12: | FSub of Id.t * Id.t 13: | FMul of Id.t * Id.t 14: | FDiv of Id.t * Id.t 15: | IfEq of Id.t * Id.t * t * t (* 比較 + 分岐 *) 16: | IfLE of Id.t * Id.t * t * t (* 比較 + 分岐 *) 17: | Let of (Id.t * Type.t) * t * t 18: | Var of Id.t 19: | LetRec of fundef list * t 20: | App of Id.t * Id.t list 21: | Tuple of Id.t list 22: | LetTuple of (Id.t * Type.t) list * Id.t * t 23: | Get of Id.t * Id.t 24: | Put of Id.t * Id.t * Id.t 25: | ExtArray of Id.t 26: | ExtFunApp of Id.t * Id.t list 27: and fundef = { name : Id.t * Type.t; args : (Id.t * Type.t) list; body : t } 28: 29: let rec fv = function (* 式に出現する(自由な)変数 *) 30: | Unit | Int(_) | Float(_) | ExtArray(_) -> S.empty 31: | Neg(x) | FNeg(x) -> S.singleton x 32: | Add(x, y) | Sub(x, y) | FAdd(x, y) | FSub(x, y) | FMul(x, y) | FDiv(x, y) | Get(x, y) -> S.of_list [x; y] 33: | IfEq(x, y, e1, e2) | IfLE(x, y, e1, e2) -> S.add x (S.add y (S.union (fv e1) (fv e2))) 34: | Let((x, t), e1, e2) -> S.union (fv e1) (S.remove x (fv e2)) 35: | Var(x) -> S.singleton x 36: | LetRec(fundefs, e2) -> 37: let (xs, zs) = 38: List.fold_left 39: (fun (xs, zs) { name = (x, t); args = yts; body = e1 } -> 40: (S.add x xs, 41: S.union zs (S.diff (fv e1) (S.of_list (List.map fst yts))))) 42: (S.empty, S.empty) 43: fundefs in 44: S.diff (S.union zs (fv e2)) xs 45: | App(x, ys) -> S.of_list (x :: ys) 46: | Tuple(xs) | ExtFunApp(_, xs) -> S.of_list xs 47: | Put(x, y, z) -> S.of_list [x; y; z] 48: | LetTuple(xs, y, e) -> S.add y (S.diff (fv e) (S.of_list (List.map fst xs))) 49: 50: let insert_let (e, t) k = (* letを挿入する補助関数 *) 51: match e with 52: | Var(x) -> k x 53: | _ -> 54: let x = Id.gentmp t in 55: let e', t' = k x in 56: Let((x, t), e, e'), t' 57: 58: let rec g env = function (* K正規化ルーチン本体 *) 59: | Syntax.Unit -> Unit, Type.Unit 60: | Syntax.Bool(b) -> Int(if b then 1 else 0), Type.Int (* 論理値true, falseを整数1, 0に変換 *) 61: | Syntax.Int(i) -> Int(i), Type.Int 62: | Syntax.Float(d) -> Float(d), Type.Float 63: | Syntax.Not(e) -> g env (Syntax.If(e, Syntax.Bool(false), Syntax.Bool(true))) 64: | Syntax.Neg(e) -> 65: insert_let (g env e) 66: (fun x -> Neg(x), Type.Int) 67: | Syntax.Add(e1, e2) -> (* 足し算のK正規化 *) 68: insert_let (g env e1) 69: (fun x -> insert_let (g env e2) 70: (fun y -> Add(x, y), Type.Int)) 71: | Syntax.Sub(e1, e2) -> 72: insert_let (g env e1) 73: (fun x -> insert_let (g env e2) 74: (fun y -> Sub(x, y), Type.Int)) 75: | Syntax.FNeg(e) -> 76: insert_let (g env e) 77: (fun x -> FNeg(x), Type.Float) 78: | Syntax.FAdd(e1, e2) -> 79: insert_let (g env e1) 80: (fun x -> insert_let (g env e2) 81: (fun y -> FAdd(x, y), Type.Float)) 82: | Syntax.FSub(e1, e2) -> 83: insert_let (g env e1) 84: (fun x -> insert_let (g env e2) 85: (fun y -> FSub(x, y), Type.Float)) 86: | Syntax.FMul(e1, e2) -> 87: insert_let (g env e1) 88: (fun x -> insert_let (g env e2) 89: (fun y -> FMul(x, y), Type.Float)) 90: | Syntax.FDiv(e1, e2) -> 91: insert_let (g env e1) 92: (fun x -> insert_let (g env e2) 93: (fun y -> FDiv(x, y), Type.Float)) 94: | Syntax.Eq _ | Syntax.NEq _ | Syntax.Lt _ | Syntax.LE _ as cmp -> 95: g env (Syntax.If(cmp, Syntax.Bool(true), Syntax.Bool(false))) 96: | Syntax.If(Syntax.Not(e1), e2, e3) -> g env (Syntax.If(e1, e3, e2)) (* notによる分岐を変換 *) 97: | Syntax.If(Syntax.Eq(e1, e2), e3, e4) -> 98: insert_let (g env e1) 99: (fun x -> insert_let (g env e2) 100: (fun y -> 101: let e3', t3 = g env e3 in 102: let e4', t4 = g env e4 in 103: IfEq(x, y, e3', e4'), t3)) 104: | Syntax.If(Syntax.NEq(e1, e2), e3, e4) -> g env (Syntax.If(Syntax.Eq(e1, e2), e4, e3)) 105: | Syntax.If(Syntax.Lt(e1, e2), e3, e4) -> g env (Syntax.If(Syntax.LE(e2, e1), e4, e3)) 106: | Syntax.If(Syntax.LE(e1, e2), e3, e4) -> 107: insert_let (g env e1) 108: (fun x -> insert_let (g env e2) 109: (fun y -> 110: let e3', t3 = g env e3 in 111: let e4', t4 = g env e4 in 112: IfLE(x, y, e3', e4'), t3)) 113: | Syntax.If(e1, e2, e3) -> g env (Syntax.If(Syntax.NEq(e1, Syntax.Bool(false)), e2, e3)) (* 比較のない分岐を変換 *) 114: | Syntax.Let((x, t), e1, e2) -> 115: let e1', t1 = g env e1 in 116: let e2', t2 = g (M.add x t env) e2 in 117: Let((x, t), e1', e2'), t2 118: | Syntax.Var(x) when M.mem x env -> Var(x), M.find x env 119: | Syntax.Var(x) -> (* 外部配列の参照 *) 120: (match M.find x !Typing.extenv with 121: | Type.Array(_) as t -> ExtArray x, t 122: | _ -> failwith (Printf.sprintf "external variable %s does not have an array type" x)) 123: | Syntax.LetRec(fundefs, e2) -> 124: let env' = 125: M.add_list 126: (List.map (fun fundef -> fundef.Syntax.name) fundefs) 127: env in 128: let e2', t2 = g env' e2 in 129: LetRec(List.map 130: (fun { Syntax.name = xt; Syntax.args = yts; Syntax.body = e1 } -> 131: let e1', t1 = g (M.add_list yts env') e1 in 132: { name = xt; args = yts; body = e1' }) 133: fundefs, 134: e2'), 135: t2 136: | Syntax.App(Syntax.Var(f), e2s) when not (M.mem f env) -> (* 外部関数の呼び出し *) 137: (match M.find f !Typing.extenv with 138: | Type.Fun(_, t) -> 139: let rec bind xs = function (* "xs" are identifiers for the arguments *) 140: | [] -> ExtFunApp(f, xs), t 141: | e2 :: e2s -> 142: insert_let (g env e2) 143: (fun x -> bind (xs @ [x]) e2s) in 144: bind [] e2s (* left-to-right evaluation *) 145: | _ -> assert false) 146: | Syntax.App(e1, e2s) -> 147: (match g env e1 with 148: | e1', Type.Fun(_, t) as et1 -> 149: insert_let et1 150: (fun f -> 151: let rec bind xs = function (* "xs" are identifiers for the arguments *) 152: | [] -> App(f, xs), t 153: | e2 :: e2s -> 154: insert_let (g env e2) 155: (fun x -> bind (xs @ [x]) e2s) in 156: bind [] e2s) (* left-to-right evaluation *) 157: | _ -> assert false) 158: | Syntax.Tuple(es) -> 159: let rec bind xs ts = function (* "xs" and "ts" are identifiers and types for the elements *) 160: | [] -> Tuple(xs), Type.Tuple(ts) 161: | e :: es -> 162: let _, t as et = g env e in 163: insert_let et 164: (fun x -> bind (xs @ [x]) (ts @ [t]) es) in 165: bind [] [] es 166: | Syntax.LetTuple(xts, e1, e2) -> 167: insert_let (g env e1) 168: (fun y -> 169: let e2', t2 = g (M.add_list xts env) e2 in 170: LetTuple(xts, y, e2'), t2) 171: | Syntax.Array(e1, e2) -> 172: insert_let (g env e1) 173: (fun x -> 174: let _, t2 as et2 = g env e2 in 175: insert_let et2 176: (fun y -> 177: let l = 178: match t2 with 179: | Type.Float -> "create_float_array" 180: | _ -> "create_array" in 181: ExtFunApp(l, [x; y]), Type.Array(t2))) 182: | Syntax.Get(e1, e2) -> 183: (match g env e1 with 184: | e1', Type.Array(t) as et1 -> 185: insert_let et1 186: (fun x -> insert_let (g env e2) 187: (fun y -> Get(x, y), t)) 188: | _ -> assert false) 189: | Syntax.Put(e1, e2, e3) -> 190: insert_let (g env e1) 191: (fun x -> insert_let (g env e2) 192: (fun y -> insert_let (g env e3) 193: (fun z -> Put(x, y, z), Type.Unit))) 194: 195: let f e = fst (g M.empty e)
alpha.mli1: val f : KNormal.t -> KNormal.t 2: val g : Id.t M.t -> KNormal.t -> KNormal.t (* for Inline.g *)
alpha.ml1: (* rename identifiers to make them unique (alpha-conversion) *) 2: 3: open KNormal 4: 5: