-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy patheval_expr.hl
176 lines (160 loc) · 6.51 KB
/
eval_expr.hl
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
(* ========================================================================== *)
(* Compilation of HOL Light functions into executable OCaml code *)
(* *)
(* Copyright (c) 2018 Alexey Solovyev *)
(* *)
(* This file is distributed under the terms of the MIT licence *)
(* ========================================================================== *)
type expr =
(* expr, (pattern, guard, body) *)
| Match of expr * (expr * expr option * expr) list
| Try of expr * (expr * expr) list
| Lambda of expr list * expr
| Tuple of expr list
| List_expr of expr list
| Let of bool * string * expr list * expr * expr option
| Let_and of expr list * expr option
| If of expr * expr * expr
| App of expr * expr
| Term of term
| Type of hol_type
| String of string
| Raw of string;;
let is_app = function App _ -> true | _ -> false;;
let is_let = function Let _ -> true | _ -> false;;
let is_match = function Match _ -> true | _ -> false;;
let is_compound = function
| Let _ | Let_and _ | Match _ | Try _ | Lambda _ -> true
| _ -> false;;
let mk_app (head, args) =
List.fold_left (fun e a -> App (e, a)) head args;;
let mk_raw s = Raw s;;
let mk_tuple = function
| [] -> Raw "()"
| [e] -> e
| es -> Tuple es;;
let mk_list_expr exprs = List_expr exprs;;
let mk_int_list ints = mk_list_expr (List.map (fun i -> mk_raw (string_of_int i)) ints);;
let mk_let_and ?(body = None) = function
| [] -> failwith "mk_let_and: empty list"
| exprs when forall is_let exprs -> Let_and (exprs, body)
| _ -> failwith "mk_let_and: all expressions must be let-expressions";;
let mk_let ?(args = []) ?(body = None) (name, expr) =
Let (false, name, args, expr, body);;
let rec chain_let = function
| [e] -> e
| Let (r, a, b, e, _) :: es ->
Let (r, a, b, e, Some (chain_let es))
| Let_and (exprs, _) :: es ->
Let_and (exprs, Some (chain_let es))
| _ -> failwith "chain_let";;
let rec append_let_body let_e body =
match let_e with
| Let_and (exprs, None) -> Let_and (exprs, Some body)
| Let_and (exprs, Some n) -> Let_and (exprs, Some (append_let_body n body))
| Let (r, a, b, e, None) -> Let (r, a, b, e, Some body)
| Let (r, a, b, e, Some n) -> Let (r, a, b, e, Some (append_let_body n body))
| _ -> failwith "append_let_body";;
let print_expr =
let let_form and_flag rec_flag =
match and_flag, rec_flag with
| true, _ -> "and"
| _, true -> "let rec"
| _ -> "let" in
let rec print_args fmt =
Format.pp_print_list ~pp_sep:(fun fmt () -> Format.pp_print_string fmt " ") (print_expr false) fmt
and print_let and_flag match_flag fmt = function
| Let (r, name, args, expr, None) ->
Format.fprintf fmt "@[<v 2>%s %s %a%s=@ %a@]@ "
(let_form and_flag r) name
print_args args (if args = [] then "" else " ")
(print_expr false) expr
| Let (r, name, args, expr, Some body) ->
let f = format_of_string
(if is_compound expr then
"@[<v 2>let%s %s %a%s=@ %a in@]@ %a"
else
"@[<hv 2>let%s %s %a%s=@ %a in@]@ %a") in
Format.fprintf fmt f
(if r then " rec" else "") name
print_args args (if args = [] then "" else " ")
(print_expr false) expr (print_expr match_flag) body
| _ -> failwith "print_let: Let expected"
and print_expr flag fmt = function
| Raw s -> Format.fprintf fmt "%s" s
| String s -> Format.fprintf fmt "\"%s\"" s
| Term tm ->
Format.fprintf fmt "`(%s):%s`"
(string_of_term tm) (string_of_type (type_of tm))
| Type ty ->
Format.fprintf fmt "`:%s`" (string_of_type ty)
| Tuple es ->
Format.fprintf fmt "(%a)"
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.pp_print_string fmt ", ")
(print_expr false)) es
| List_expr es ->
Format.fprintf fmt "[%a]"
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.pp_print_string fmt "; ")
(print_expr false)) es
| Lambda (args, body) ->
Format.fprintf fmt "@[<v 2>fun %a ->@,%a@]"
print_args args (print_expr flag) body
| If (c, t, e) ->
Format.fprintf fmt "@[<v 2>if %a then@ %a@;<1 -2>else@ %a@]"
(print_expr false) c (print_expr flag) t (print_expr flag) e
| App (f, x) ->
let f1 = format_of_string "%a" in
let f2 = format_of_string (if is_app x then " (%a)" else " %a") in
Format.fprintf fmt (f1 ^^ f2) (print_expr false) f (print_expr false) x
| Let _ as expr -> print_let false flag fmt expr
| Let_and (expr1 :: exprs, None) ->
Format.fprintf fmt "@[<v>%a%a@]"
(print_let false flag) expr1
(Format.pp_print_list ~pp_sep:(fun fmt () -> ()) (print_let true flag)) exprs
| Let_and (expr1 :: exprs, Some body) ->
Format.fprintf fmt "@[<v>%a%a in@]@ %a"
(print_let false flag) expr1
(Format.pp_print_list ~pp_sep:(fun fmt () -> ()) (print_let true flag)) exprs
(print_expr flag) body
| Let_and _ -> failwith "Let_and: empty list"
| Try (expr, cases) ->
Format.fprintf fmt "@[<v 2>try@ %a@]@ with@,| %a"
(print_expr false) expr
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.pp_print_string fmt "| ")
(fun fmt (pat, body) ->
let f = format_of_string
(if is_compound body then
"@[<v>%a ->@ %a@]@,"
else
"@[<hv>%a ->@ %a@]@,") in
Format.fprintf fmt f
(print_expr false) pat (print_expr true) body)) cases
| Match (expr, cases) ->
let print_guard fmt = function
| None -> Format.pp_print_string fmt ""
| Some g -> Format.fprintf fmt " when %a" (print_expr false) g in
let f' = format_of_string "match %a with@,| %a" in
let f = if flag then "(" ^^ f' ^^ ")" else f' in
Format.fprintf fmt f
(print_expr false) expr
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.pp_print_string fmt "| ")
(fun fmt (pat, guard, body) ->
let f = format_of_string
(if is_compound body then
"@[<v>%a%a ->@ %a@]@,"
else
"@[<hv>%a%a ->@ %a@]@,") in
Format.fprintf fmt f
(print_expr false) pat
print_guard guard
(print_expr true) body)) cases in
print_expr false;;
let print_exprs fmt exprs =
if exprs <> [] then
let sep fmt () = Format.fprintf fmt ";;@,@," in
Format.fprintf fmt "@[<v>%a;;@]@."
(Format.pp_print_list ~pp_sep:sep print_expr) exprs;;