lambda/lambda.ml

131 lines
3.9 KiB
OCaml
Raw Normal View History

2018-02-13 23:43:40 +00:00
open Lexer
open Lexing
open Parser
open Types
2018-02-20 11:19:49 +00:00
exception UnboundVariable of string
2018-02-16 11:22:07 +00:00
exception EvaluationComplete
2018-02-20 11:04:09 +00:00
(*
2018-02-20 20:46:39 +00:00
((\a.(\b.((a a) b))) (\a.(\b.a))) (\a.(\b.a)) = (\a.(\b.a))
((\a.(\b.((a b) a))) (\a.(\b.a))) (\a.(\b.b)) = (\a.(\b.b))
(\n.\f.\x.f ((n f) x)) (\f.\x.x)
2018-02-20 11:04:09 +00:00
*)
2018-02-20 20:46:39 +00:00
let debug = true
let print_debug str =
if debug then print_endline str else ()
2018-02-20 11:04:09 +00:00
let rec string_of_term (t: Types.term) =
2018-02-13 23:43:40 +00:00
match t with
| TmAbs(x, t1) ->
2018-02-16 11:22:07 +00:00
"(\\" ^ x ^ "." ^ (string_of_term t1) ^ ")"
2018-02-13 23:43:40 +00:00
| TmApp(t1, t2) ->
2018-02-16 11:22:07 +00:00
"(" ^ (string_of_term t1) ^ " " ^ (string_of_term t2) ^ ")"
| TmVar(x) -> x
2018-02-20 11:23:05 +00:00
let rec string_of_term_in_ctx ctx tm =
match ctx with
| [] -> (string_of_term tm)
| (n, t)::r -> if t = tm then n else (string_of_term_in_ctx r tm)
2018-02-20 11:04:09 +00:00
let rec string_of_ctx (c: Types.context) =
match c with
| [] -> ""
| (n, t)::r -> (n ^ ": " ^ (string_of_term t) ^ "\n" ^ (string_of_ctx r))
2018-02-16 11:22:07 +00:00
2018-02-20 11:04:09 +00:00
let assign ctx (name, t) : Types.context =
2018-02-16 11:22:07 +00:00
(name, t)::ctx
2018-02-20 11:04:09 +00:00
let remove ctx name =
List.filter (fun (a, b) -> a != name) ctx
let rec lookup ctx name : Types.term =
2018-02-16 11:22:07 +00:00
match ctx with
2018-02-20 11:19:49 +00:00
| [] -> raise (UnboundVariable name)
2018-02-16 11:22:07 +00:00
| (n, t)::tail ->
if n = name then t else lookup tail name
2018-02-20 11:04:09 +00:00
let rec subst name tm repl =
match tm with
| TmVar(x) -> if x = name then repl else TmVar(x)
| TmAbs(n, t) -> if n = name then TmAbs(n, t) else TmAbs(n, subst name t repl)
| TmApp(a, b) -> TmApp(subst name a repl, subst name b repl)
let rec try_subst name tm repl =
match tm with
2018-02-20 20:46:39 +00:00
| TmVar(x) ->
if x = name then
(true, repl)
else
(false, TmVar(x))
| TmAbs(n, t) ->
if n = name then
let (s, t') = try_subst n t (TmVar n) in
(false, TmAbs(n, t'))
else
let (s, t') = try_subst name t repl in
(s, TmAbs(n, t'))
| TmApp(a, b) ->
let ((sa, a'), (sb, b')) = (try_subst name a repl, try_subst name b repl) in
(sa || sb, TmApp(a', b'))
2018-02-20 11:04:09 +00:00
2018-02-16 11:22:07 +00:00
let rec eval (ctx, t) =
2018-02-20 11:04:09 +00:00
let rec helper (ctx, t) d =
2018-02-20 20:46:39 +00:00
print_debug ((String.init (d * 2) (fun _ -> ' ')) ^ "helper" ^ (string_of_term t));
print_debug (string_of_ctx ctx);
2018-02-20 11:04:09 +00:00
match t with
| TmApp(TmApp(_, _) as a, b) ->
let (_, a') = helper (ctx, a) (d + 1) in
helper (ctx, TmApp(a', b)) (d + 1)
| TmApp(TmAbs(n, t), r) ->
(* let ctx' = assign ctx (n, r) in
helper (ctx', t) (d + 1) *)
let (s, t') = try_subst n t r in
2018-02-20 20:46:39 +00:00
print_debug ("try_subst('" ^ n ^ "', " ^ (string_of_term t) ^ ", " ^ (string_of_term r) ^ ") = " ^ (if s then "true" else "false"));
2018-02-20 11:04:09 +00:00
if s then helper (ctx, t') (d + 1) else (ctx, t')
| TmApp(TmVar(n), b) ->
let (_, a) = helper (ctx, lookup ctx n) (d + 1) in
helper (ctx, TmApp(a, b)) (d + 1)
| TmVar(n) -> (ctx, lookup ctx n)
| TmAbs(_, TmVar(_)) as t -> (ctx, t)
| TmAbs(n, _) as t ->
let r = TmVar(n) in
let (s, t') = try_subst n t r in
2018-02-20 20:46:39 +00:00
print_debug ("try_subst('" ^ n ^ "', " ^ (string_of_term t) ^ ", " ^ (string_of_term r) ^ ") = " ^ (if s then "true" else "false"));
2018-02-20 11:04:09 +00:00
if s then helper (ctx, t') (d + 1) else (ctx, t')
2018-02-16 11:22:07 +00:00
in try
2018-02-20 11:04:09 +00:00
let (ctx', t') = helper (ctx, t) 0 in
if t = t' then raise EvaluationComplete else
2018-02-16 11:22:07 +00:00
eval (ctx', t')
2018-02-20 11:19:49 +00:00
with
2018-02-20 11:49:46 +00:00
| UnboundVariable v -> raise (Failure ("unbound variable '" ^ v ^ "'"))
2018-02-20 20:46:39 +00:00
| EvaluationComplete ->
print_debug "evaluation complete";
(ctx, t)
2018-02-13 23:43:40 +00:00
let _ =
2018-02-20 11:49:46 +00:00
let rec loop ctx =
try
2018-02-13 23:43:40 +00:00
print_string "> "; flush stdout;
2018-02-20 11:58:36 +00:00
let lexbuf = Lexing.from_channel stdin in
2018-02-20 09:24:52 +00:00
let x = Parser.main Lexer.token lexbuf in
match x with
| Types.Term t ->
let (ctx', r) = eval (ctx, t) in
2018-02-20 11:23:05 +00:00
print_endline (string_of_term_in_ctx ctx r); flush stdout;
2018-02-20 09:24:52 +00:00
loop ctx'
| Types.Assign (n, t) ->
let (ctx', r) = eval (ctx, t) in
2018-02-20 11:19:49 +00:00
loop (assign ctx' (n, r))
2018-02-20 11:49:46 +00:00
with
| Lexer.Eof ->
loop ctx
| End_of_file ->
print_endline "^D";
exit 0
in loop []