composition calculus
あなごるに出てた composition calculus が面白そうで,真面目にインタプリタを書いてみたくなったので OCaml で実装してみた。所要時間は Stream のインタフェースを思い出すところから始めて全部で一時間くらい。
type token = char type expr = Atom of token | App of expr * expr let dot = Atom '.' let rec read_token stream = let c = Stream.next stream in if c = ' ' then read_token stream else c let tokenize_string string = let rec loop s a = if Stream.peek s = None then List.rev_map (fun t -> Atom t) a else loop s (read_token s :: a) in loop (Stream.of_string string) [] let parse string = match tokenize_string string with | t::tks -> List.fold_left (fun x y -> App (x, y)) t tks | [] -> failwith "invalid input" let rec eval = function | Atom _ as e -> e | App(e, e') -> let f = eval e in let a = eval e' in match f with | App(App(f, e0), e1) when f = dot -> eval (App(e0, App(e1, a))) | _ -> App(f, a) let rec string_of_expr = function | Atom c -> String.make 1 c | App(e, e') -> "(" ^ string_of_expr e ^ " " ^ string_of_expr e' ^ ")" let rec doit () = try let string = read_line () in print_endline (string_of_expr (eval (parse string))); doit () with End_of_file -> () let _ = doit ()
値の型を式とは区別するようにしたり,dot が fully applied じゃないまま残る場合も考慮したり,CPS 変換したり,あるいは機能を追加してみたり,などなどをやればまだいろいろ楽しめるんじゃないかと。今度やるかも。