1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
(** Copyright 2026, Kirill K. Smirnov *)
(** SPDX-License-Identifier: LGPL-3.0-or-later *)
open Ast
let rec compile_to_lambda_cbv : mlterm -> Lambda.lterm = function
| App (Var "not", t) -> compile_to_lambda_cbv (ITE (t, Bool false, Bool true))
| Var "fst" -> Abs ("p", App (Var "p", Lambda.ltrue))
| Var "snd" -> Abs ("p", App (Var "p", Lambda.lfalse))
| Var "inl" -> Abs ("x", Abs ("f", Abs ("g", App (Var "f", Var "x"))))
| Var "inr" -> Abs ("x", Abs ("f", Abs ("g", App (Var "g", Var "x"))))
| App (App (Var "&&", t1), t2) -> compile_to_lambda_cbv (ITE (t1, t2, Bool false))
| App (App (Var "||", t1), t2) -> compile_to_lambda_cbv (ITE (t1, Bool true, t2))
| Constr e -> Var e
| Var x -> Var x
| Int i -> Int i
| Bool true -> Lambda.ltrue
| Bool false -> Lambda.lfalse
| Unit -> Unit
| ITE (c, th, e) ->
let cl = compile_to_lambda_cbv c in
let thl = compile_to_lambda_cbv th in
let el = compile_to_lambda_cbv e in
let u = Lambda.fresh_var (Lambda.vars cl @ Lambda.vars thl @ Lambda.vars el) in
App (App (App (cl, Abs (u, thl)), Abs (u, el)), Unit)
| Let (v, t1, t2) -> App (Abs (v, compile_to_lambda_cbv t2), compile_to_lambda_cbv t1)
| LetRec (v, t1, t2) ->
App
( Abs (v, compile_to_lambda_cbv t2)
, App (Lambda.fix_comb_cbv, Abs (v, compile_to_lambda_cbv t1)) )
| LetExc (_, _, t) -> compile_to_lambda_cbv t
| App (t1, t2) -> App (compile_to_lambda_cbv t1, compile_to_lambda_cbv t2)
| Fun (x, t) -> Abs (x, compile_to_lambda_cbv t)
| Pair (t1, t2) ->
App
( App
( Abs ("x", Abs ("y", Abs ("f", App (App (Var "f", Var "x"), Var "y"))))
, compile_to_lambda_cbv t1 )
, compile_to_lambda_cbv t2 )
| Match (t, v1, t1, v2, t2) ->
let tl = compile_to_lambda_cbv t in
let t1l = compile_to_lambda_cbv t1 in
let t2l = compile_to_lambda_cbv t2 in
App (App (tl, Abs (v1, t1l)), Abs (v2, t2l))
| Try (t, l) ->
Lambda.Try
( compile_to_lambda_cbv t
, List.map (fun (s, v, t) -> s, Lambda.Abs (v, compile_to_lambda_cbv t)) l )
;;
let parse str =
let lexer = Lexing.from_string str in
try Parser.prog Lexer.token lexer with
| Parser.Error ->
let pos = lexer.Lexing.lex_curr_p in
let line = pos.Lexing.pos_lnum in
let char = pos.Lexing.pos_cnum - pos.Lexing.pos_bol in
let () = Printf.eprintf "Parser error at line %d, character %d\n" line char in
raise (Failure "Parser error")
;;
let interp str =
let ml_ast = parse str in
let tp = Typing.hm_typechecker ml_ast in
let l_ast = compile_to_lambda_cbv ml_ast in
Lambda.beta_reduce Lambda.beta_step_in_cbv l_ast, tp
;;