Skip to content

Commit a58b904

Browse files
authored
Merge pull request #114 from aqjune-aws/nativecomp
Support native compilation of HOL Light, add unit tests
2 parents 6f137d9 + f566904 commit a58b904

File tree

8 files changed

+125
-25
lines changed

8 files changed

+125
-25
lines changed

.github/workflows/main.yml

+21-5
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ jobs:
1818
test1:
1919
runs-on: ubuntu-22.04
2020
name: OCaml 4.05, Camlp5 7.10
21-
21+
2222
steps:
2323
- name: Install dependency
2424
run: |
2525
sudo apt update && sudo apt install -y opam
2626
opam init --disable-sandboxing --compiler=4.05.0
2727
opam pin -y add camlp5 7.10
28-
opam install -y num
28+
opam install -y num ledit
2929
3030
- name: Checkout this repo
3131
uses: actions/checkout@v2
@@ -37,13 +37,14 @@ jobs:
3737
cd hol-light
3838
eval $(opam env)
3939
make
40-
./hol.sh | tee log.txt
40+
./hol.sh 2>&1 | tee log.txt
4141
! grep "Error" log.txt
42+
grep "Camlp5 parsing version" log.txt
4243
4344
test2:
4445
runs-on: ubuntu-22.04
4546
name: OCaml 4.14, Camlp5 8.03 (make switch)
46-
47+
4748
steps:
4849
- name: Install dependency
4950
run: |
@@ -61,5 +62,20 @@ jobs:
6162
make switch
6263
eval $(opam env)
6364
make
64-
./hol.sh | tee log.txt
65+
./hol.sh 2>&1 | tee log.txt
66+
! grep "Error" log.txt
67+
grep "Camlp5 parsing version (HOL-Light)" log.txt
68+
cd ..
69+
70+
- name: Run (HOLLIGHT_USE_MODULE=1)
71+
run: |
72+
cd hol-light
73+
eval $(opam env)
74+
make clean
75+
export HOLLIGHT_USE_MODULE=1
76+
make
77+
./hol.sh 2>&1 | tee log.txt
6578
! grep "Error" log.txt
79+
grep "Camlp5 parsing version (HOL-Light)" log.txt
80+
./unit_tests.byte
81+
./unit_tests.native

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
.DS_Store
22
.vscode
33
_opam
4+
*.a
45
*.cma
56
*.cmi
67
*.cmo
78
*.o
89
*.cmx
10+
*.cmxa
911
pa_j.ml
1012
update_database.ml
1113
ocaml-hol
1214
hol.sh
1315
hol_lib_inlined.ml
16+
unit_tests_inlined.ml
17+
unit_tests.byte
18+
unit_tests.native

Makefile

+42-8
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ CAMLP5_VERSION=`camlp5 -v 2>&1 | cut -f3 -d' ' | cut -f1-3 -d'.' | cut -f1 -d'-'
3737

3838
# If set to 1, build hol_lib.cmo and make hol.sh to use it.
3939
# NOTE: This extends the trusted base of HOL Light to include the inliner
40-
# script, inline_loads.ml. inline_loads.ml is an OCaml program that receives
40+
# script, inline_load.ml. inline_load.ml is an OCaml program that receives
4141
# an HOL Light proof and replaces the loads/loadt/needs function invocations
4242
# with their actual contents. Please turn this flag on only if having this
4343
# additional trusted base is considered okay.
@@ -53,7 +53,7 @@ default: update_database.ml pa_j.cmo hol.sh;
5353
# HOL Light.
5454
# ledit is installed for line editing of OCaml REPL
5555
switch:; \
56-
opam update ; \
56+
opam update ; \
5757
opam switch create . ocaml-base-compiler.4.14.0 ; \
5858
eval $(opam env) ; \
5959
opam install -y zarith ledit ; \
@@ -115,14 +115,35 @@ bignum.cmo: bignum_zarith.ml bignum_num.ml ; \
115115
else ocamlc -c -o bignum.cmo bignum_num.ml ; \
116116
fi
117117

118+
bignum.cmx: bignum_zarith.ml bignum_num.ml ; \
119+
if test ${OCAML_VERSION} = "4.14" -o ${OCAML_UNARY_VERSION} = "5" ; \
120+
then ocamlfind ocamlopt -package zarith -c -o bignum.cmx bignum_zarith.ml ; \
121+
else ocamlopt -c -o bignum.cmx bignum_num.ml ; \
122+
fi
123+
118124
hol_loader.cmo: hol_loader.ml ; \
119125
ocamlc -verbose -c hol_loader.ml -o hol_loader.cmo
120126

121-
hol_lib.cmo: inline_load.ml hol_lib.ml hol_loader.cmo ; \
122-
ocaml inline_load.ml hol_lib.ml hol_lib_inlined.ml ; \
123-
ocamlc -verbose -c -pp "camlp5r pa_lexer.cmo pa_extend.cmo q_MLast.cmo -I . pa_j.cmo" hol_loader.cmo hol_lib_inlined.ml bignum.cmo -o hol_lib.cmo ; \
127+
hol_loader.cmx: hol_loader.ml ; \
128+
ocamlopt -verbose -c hol_loader.ml -o hol_loader.cmx
129+
130+
hol_lib_inlined.ml: hol_lib.ml inline_load.ml ; \
131+
HOLLIGHT_DIR="`pwd`" ocaml inline_load.ml hol_lib.ml hol_lib_inlined.ml -omit-prelude
132+
133+
hol_lib.cmo: pa_j.cmo hol_lib_inlined.ml hol_loader.cmo bignum.cmo ; \
134+
ocamlc -verbose -c -pp "camlp5r pa_lexer.cmo pa_extend.cmo q_MLast.cmo -I . pa_j.cmo" hol_loader.cmo hol_lib_inlined.ml bignum.cmo -o hol_lib.cmo
135+
136+
hol_lib.cma: hol_lib.cmo bignum.cmo hol_loader.cmo ; \
124137
ocamlfind ocamlc -package zarith -linkpkg -a -o hol_lib.cma bignum.cmo hol_loader.cmo hol_lib.cmo
125138

139+
hol_lib.cmx: pa_j.cmo hol_lib_inlined.ml hol_loader.cmx bignum.cmx ; \
140+
OCAMLRUNPARAM=l=1000000000 ocamlopt.byte -verbose -c \
141+
-pp "camlp5r pa_lexer.cmo pa_extend.cmo q_MLast.cmo -I . pa_j.cmo" \
142+
hol_lib_inlined.ml hol_loader.cmx bignum.cmx -o hol_lib.cmx
143+
144+
hol_lib.cmxa: hol_lib.cmx hol_loader.cmx bignum.cmx ; \
145+
ocamlfind ocamlopt -package zarith -a -o hol_lib.cmxa bignum.cmx hol_loader.cmx hol_lib.cmx
146+
126147
# Create a bash script 'hol.sh' that loads 'hol.ml' in OCaml REPL.
127148

128149
hol.sh: pa_j.cmo ${HOLSRC} bignum.cmo hol_loader.cmo update_database.ml
@@ -140,9 +161,20 @@ hol.sh: pa_j.cmo ${HOLSRC} bignum.cmo hol_loader.cmo update_database.ml
140161
fi
141162

142163
# If HOLLIGHT_USE_MODULE is set, add hol_lib.cmo to dependency of hol.sh
164+
# Also, build unit_tests using OCaml bytecode compiler as well as OCaml native compiler.
143165

144166
ifeq ($(HOLLIGHT_USE_MODULE),1)
145167
hol.sh: hol_lib.cmo
168+
unit_tests_inlined.ml: unit_tests.ml inline_load.ml ; \
169+
HOLLIGHT_DIR="`pwd`" ocaml inline_load.ml unit_tests.ml unit_tests_inlined.ml
170+
unit_tests.byte: unit_tests_inlined.ml hol_lib.cmo inline_load.ml hol.sh ; \
171+
ocamlfind ocamlc -package zarith -linkpkg -pp "`./hol.sh -pp`" \
172+
-I . bignum.cmo hol_loader.cmo hol_lib.cmo unit_tests_inlined.ml -o unit_tests.byte
173+
unit_tests.native: unit_tests_inlined.ml hol_lib.cmx inline_load.ml hol.sh ; \
174+
ocamlfind ocamlopt -package zarith -linkpkg -pp "`./hol.sh -pp`" \
175+
-I . bignum.cmx hol_loader.cmx hol_lib.cmx unit_tests_inlined.ml -o unit_tests.native
176+
177+
default: hol_lib.cma unit_tests.byte unit_tests.native
146178
endif
147179

148180
# TODO: update this and hol.* commands to use one of checkpointing tools
@@ -205,7 +237,9 @@ install: hol.sh hol hol.multivariate hol.sosa hol.card hol.complex; cp hol hol.m
205237
# Clean up all compiled files
206238

207239
clean:; \
208-
rm -f bignum.cmo update_database.ml pa_j.ml pa_j.cmi pa_j.cmo \
209-
hol_lib.cmo hol_lib.cmi hol_lib.cma hol_lib_inlined.ml \
210-
hol_loader.cmo hol_loader.cmi \
240+
rm -f bignum.c* bignum.o \
241+
update_database.ml pa_j.ml pa_j.cmi pa_j.cmo \
242+
hol_lib.a hol_lib.c* hol_lib.o hol_lib_inlined.ml \
243+
hol_loader.c* hol_loader.o \
244+
unit_tests_inlined.* unit_tests.native unit_tests.byte \
211245
ocaml-hol hol.sh hol hol.multivariate hol.sosa hol.card hol.complex

README

+11-7
Original file line numberDiff line numberDiff line change
@@ -263,20 +263,24 @@ checkpointing programs.
263263
COMPILING HOL LIGHT
264264

265265
Running 'HOLLIGHT_USE_MODULE=1 make' will compile hol_lib.ml and generate
266-
hol_lib.cmo. This will also create hol.sh which will configure hol.ml to use
267-
the compiled hol_lib.cmo. Compiling HOL Light will only work on OCaml 4.14
268-
or above.
266+
hol_lib.cmo/hol_lib.cmx. This will also create hol.sh which will configure
267+
hol.ml to use the compiled hol_lib.cmo (but not hol_lib.cmx). Compiling
268+
HOL Light will only work on OCaml 4.14 or above.
269269

270-
To compile an OCaml file that opens Hol_lib, use the following command.
270+
To compile an OCaml file that opens Hol_lib using OCaml bytecode compiler,
271+
use the following command. For OCaml native compiler, replace ocamlc with
272+
ocamlopt.
271273

272-
ocamlfind ocamlc -package zarith -linkpkg -pp \
273-
"camlp5r pa_lexer.cmo pa_extend.cmo q_MLast.cmo -I . (HOL dir)pa_j.cmo" \
274+
ocamlfind ocamlc -package zarith -linkpkg -pp "`./hol.sh -pp`" \
274275
-I (HOL dir) (HOL dir)/bignum.cmo (HOL dir)/hol_loader.cmo \
275-
(HOL dir)/hol_lib.cmo (input.ml) -o (output.ml)
276+
(HOL dir)/hol_lib.cmo (input.ml) -o (output)
276277

277278
The load functions (loads/loadt/needs) are not available anymore in this
278279
approach. Please use 'ocaml inline_loads.ml <input.ml> <output.ml>' to inline
279280
their invocations.
281+
For native compilation, if it raises the stack overflow error, either (1)
282+
try ocamlopt.byte with OCAMLRUNPARAM=l=(some large number), or (2) increase
283+
the stack size using `ulimit`.
280284

281285
NOTE: Compiling HOL Light with 'HOLLIGHT_USE_MODULE=1' extends the trusted base
282286
of HOL Light to include the inliner script, inline_loads.ml. inline_loads.ml is

hol_4.14.sh

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
#!/bin/bash
22

3+
if [ "$#" -eq 1 ] && [ "$1" == "-pp" ]; then
4+
echo "camlp5r pa_lexer.cmo pa_extend.cmo q_MLast.cmo -I "__DIR__" pa_j.cmo"
5+
exit 0
6+
fi
7+
38
# The default ocaml REPL does not accept arrow keys.
49
# Export LINE_EDITOR to a proper program to enable this before invoking this
510
# script. If not set, ledit will be used.

hol_4.sh

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
#!/bin/bash
22

3+
if [ "$#" -eq 1 ] && [ "$1" == "-pp" ]; then
4+
echo "camlp5r pa_lexer.cmo pa_extend.cmo q_MLast.cmo -I "__DIR__" pa_j.cmo"
5+
exit 0
6+
fi
7+
38
# The default ocaml REPL does not accept arrow keys.
49
# Export LINE_EDITOR to a proper program to enable this before invoking this
510
# script. If not set, ledit will be used.

inline_load.ml

+23-5
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,24 @@
1010
(* (c) Copyright, Juneyoung Lee 2024 *)
1111
(* ========================================================================= *)
1212

13-
if Array.length Sys.argv <> 3 then
14-
let _ = Printf.eprintf "inline_load.ml <input.ml> <output.ml>\n" in
13+
let argn = Array.length Sys.argv;;
14+
15+
if argn < 3 || argn > 4 then
16+
let _ = Printf.eprintf "inline_load.ml <input.ml> <output.ml> [-omit-prelude]\n" in
17+
let _ = Printf.eprintf " -omit-prelude: omit 'open Hol_lib;;' and 'open Hol_loader;;'.\n" in
1518
exit 1;;
1619

20+
try
21+
let v = Sys.getenv "HOLLIGHT_DIR" in
22+
if v = "" then Printf.printf "Warning: HOLLIGHT_DIR is not set\n%!"
23+
with Not_found -> Printf.printf "Warning: HOLLIGHT_DIR is not set\n%!";;
24+
1725
let filename = Sys.argv.(1);;
1826
let fout = open_out (Sys.argv.(2));;
27+
let omit_prelude = argn >= 4 && Sys.argv.(3) = "-omit-prelude";;
28+
29+
if not omit_prelude then
30+
Printf.fprintf fout "open Hol_lib;;\nopen Hol_loader;;\n";;
1931

2032
#use "hol_loader.ml";;
2133

@@ -50,14 +62,20 @@ file_loader := fun filename ->
5062
let open Printf in
5163
fprintf fout "(* %s *)\n" filename;
5264
let lines = strings_of_file filename in
65+
let fail_if_nonexistent f x = try f x with _ -> failwith x in
5366
List.iter
5467
(fun line ->
5568
match parse_load_statement "loadt" line with
56-
| Some (path,line') -> loadt path; fprintf fout "%s\n" line' | None ->
69+
| Some (path,line') -> fail_if_nonexistent loadt path; fprintf fout "%s\n" line' | None ->
5770
(match parse_load_statement "loads" line with
58-
| Some (path,line') -> loads path; fprintf fout "%s\n" line' | None ->
71+
| Some (path,line') -> begin
72+
if path = "update_database.ml"
73+
then Printf.printf "Warning: 'loads \"update_database.ml\";;' is omitted\n"
74+
else (fail_if_nonexistent loads path; fprintf fout "%s\n" line')
75+
end
76+
| None ->
5977
(match parse_load_statement "needs" line with
60-
| Some (path,line') -> needs path; fprintf fout "%s\n" line'
78+
| Some (path,line') -> fail_if_nonexistent needs path; fprintf fout "%s\n" line'
6179
| None -> fprintf fout "%s\n" line (* no linebreak needed! *))))
6280
lines;
6381
(* add digest *)

unit_tests.ml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
(* ========================================================================= *)
2+
(* HOL LIGHT unit tests *)
3+
(* ========================================================================= *)
4+
5+
(* ------------------------------------------------------------------------- *)
6+
(* Test verbose descriptive names for quantifiers/logical consts. *)
7+
(* ------------------------------------------------------------------------- *)
8+
9+
assert (`T` = `true`);;
10+
assert (`F` = `false`);;
11+
assert (`!(x:A). P x` = `forall (x:A). P x`);;
12+
assert (`?(x:A). P x` = `exists (x:A). P x`);;
13+
assert (`?!(x:A). P x` = `existsunique (x:A). P x`);;

0 commit comments

Comments
 (0)